2012-06-26 16 views
8

Ich mache ein Projekt in Python (3.2), für das ich benutzerdefinierte Objekte vergleichen muss. Ich bin es gewohnt, in Java OOP, wo man würde eine compareTo() Methode in der Klasse definieren, die die natürliche Ordnung dieser Klasse gibt an, wie im Beispiel unten:Python entspricht Java's compareTo()

public class Foo { 
    int a, b; 

    public Foo(int aa, int bb) { 
     a = aa; 
     b = bb; 
    } 

    public int compareTo(Foo that) { 
     // return a negative number if this < that 
     // return 0 if this == that 
     // return a positive number if this > that 

     if (this.a == that.a) return this.b - that.b; 
     else return this.a - that.a; 
    } 
} 

Ich bin ziemlich neu in Klassen/Objekte in Python, also würde ich gerne wissen, was ist der "pythonische" Weg, um die natürliche Ordnung einer Klasse zu definieren?

+1

Du meinst, wie [ '__cmp__'] (http : //docs.python.org/reference/datamodel.html#object.__cmp__)? –

Antwort

10

Sie können die speziellen Methoden __lt__, __gt__ usw. implementieren, um die Standardoperatoren für benutzerdefinierte Typen zu implementieren. Sehen Sie mehr über sie in der language reference.

Zum Beispiel:

class Foo: 
    def __init__ (self, a, b): 
     self.a = a 
     self.b = b 

    def __lt__ (self, other): 
     if self.a == other.a: 
      return self.b < other.b 
     return self.a < other.b 

    def __gt__ (self, other): 
     return other.__lt__(self) 

    def __eq__ (self, other): 
     return self.a == other.b and self.b == other.b 

    def __ne__ (self, other): 
     return not self.__eq__(other) 

Oder wie gesagt von Stranac in den Kommentaren, können Sie den total_ordering Dekorateur verwenden eine Eingabe zu speichern:

@functools.total_ordering 
class Foo: 
    def __init__ (self, a, b): 
     self.a = a 
     self.b = b 

    def __lt__ (self, other): 
     if self.a == other.a: 
      return self.b < other.b 
     return self.a < other.b 

    def __eq__ (self, other): 
     return self.a == other.b and self.b == other.b 
+3

Sie könnten auch' __lt__' und '__eq__' definieren und den' functools.total_ordering' Dekorator verwenden. – stranac

+1

In Python 2 wird '__gt__' automatisch' nicht __lt__' falls nicht angegeben (nur getestet). Seltsam, dass die Dokumentation etwas anderes sagt. Jemand möchte es auf Python 3 testen, vielleicht @stranac? – schlamar

+0

Sie haben Recht, aber es ist möglich, dass die Dokumentation tatsächlich nur auf das Inverse verweist, dh 'not (a < b) == (a > = b)' (wobei letzteres eine Exception auslöst, wenn sie nicht definiert ist) Parameter wenn möglich. – poke

6

Python hat eine ähnliche Funktion: __cmp__().

ich Sie jetzt sehen, sind zu fragen über Python 3. Their "whats new" suggests:

 
The cmp() function should be treated as gone, and the __cmp__() special method 
is no longer supported. Use __lt__() for sorting, __eq__() with __hash__(), and 
other rich comparisons as needed. (If you really need the cmp() functionality, 
you could use the expression (a > b) - (a < b) as the equivalent for cmp(a, b).) 

So scheint es, man immer etwas tun könnte, wie

def compareTo(self, that): 
    return ((self > that) - (self < that)) 

oder

@classmethod 
def compare(cls, a, b): 
    return ((a > b) - (a < b)) 

nach der Implementierung __gt__() und __lt__().

die Sie dann wie verwenden würden:

f1 = Foo(1,1) 
f2 = Foo(2,2) 

f1.compareTo(f2) 
Foo.compare(f1,f2) 

Sie Dies würde gleichwertige Funktionalität.

+3

'__cmp__' existiert nicht mehr in Python 3 und OP fragt nach Python 3. – poke