2016-06-17 9 views
0

Im folgenden Code, I ‚definierte <‘ in der magischen Methode __lt__(), die True wenn das erste Argument kleiner ist als die zweite, falsche Rück sonst zurück.Python3: Warum wird der Vergleich natürlich gemacht?

from functools import total_ordering 

@total_ordering 
class Currency: 
    """ 
    One object of class Currency stores one amount of money, dollars and cents. 
    """ 

    def __add__(self, other): 
     """ 
     returns the result of adding self to other 
     """ 
     total = Currency(self.dollars, self.cents) 
     total.dollars = total.dollars + other.dollars 
     print (other.dollars) 
     total.cents = total.cents + other.cents 
     print (other.cents) 
     if total.cents > 100: 
      total.cents = total.cents - 100 
      total.dollars = total.dollars +1 
     return total 

    def __init__(self, dollars=0, cents=0): 
     self.dollars = dollars 
     self.cents = cents 

    def __str__(self): 
     return "$"+str(self.dollars)+"."+str(self.cents) 

    def __eq__(self, other): 
     return self.dollars==other.dollars and self.cents==other.cents  

    def __lt__(self, other): 
     if self.dollars<other.dollars: 
      return True 
     elif self.dollars > other.dollars: 
      return False 
     else: # dollars are equal 
      return self.cents < other.cents 

Und dann rief ich __lt__() im Testprogramm mit '<'. In diesem Fall ist candyPrice (erstes Argument) weniger als bookPrice (zweites Argument), so dass True wie erwartet zurückgegeben wurde. Und dann habe ich diese zwei Werte mit '>' verglichen, was in class Currency nicht vordefiniert war, aber es gab auch False wie erwartet zurück. Also frage ich mich, wenn es ist, weil __lt__() bereits definiert wurde, dann wurde der entgegengesetzte Ausdruck, der '>' Ausdruck, auch implizit definiert?

if __name__ == "__main__": 
    candyPrice = Currency (1, 17) # $1.17 
    bookPrice = Currency (12, 99) # $12.99 

    print (candyPrice < bookPrice) 
    print (candyPrice > bookPrice) 
+0

Haben Sie Ihr Programm mit Argumenten getestet, die gleiche Preise haben? – Kairat

+0

@Kairat Ja, habe ich. Und ich werde es meiner Frage hinzufügen. Danke –

+0

Versuchen Sie, eine 'print'-Anweisung in den Vergleich zu setzen, und das wird zeigen, was aufgerufen wird. Im Allgemeinen ist * no *, '__gt__' nicht definiert.Ich denke (nicht sicher), dass es herausfinden könnte, dass 'candy> book 'dasselbe ist wie' book dwanderson

Antwort

3

Sie verwendet, um die @total_ordering Klasse Dekorateur. Dieser Decorator fügt explizit die anderen Methoden für Sie hinzu.

Vom @functools.total_ordering documentation:

Bei einer Klasse definieren, eine oder mehr reiche Vergleich Bestellmethoden, diese Klasse Dekorateur liefert den Rest. Dies vereinfacht den Aufwand in alle möglichen reichen Vergleichsoperationen spezifizieren:

Die Klasse eines __lt__() definieren müssen, __le__(), __gt__() oder __ge__(). Zusätzlich sollte die Klasse eine __eq__() Methode bereitstellen.

Also auch wenn Sie keine __gt__ Methode, die Klasse Dekorateur hat man definiert haben definiert, damit Sie Ihre __lt__ Methode, zusammen mit __eq__.

Wenn zum Beispiel ein __lt__ Verfahren definiert, wobei die __gt__() Implementierung ist eingestellt auf:

def _gt_from_lt(self, other, NotImplemented=NotImplemented): 
    'Return a > b. Computed by @total_ordering from (not a < b) and (a != b).' 
    op_result = self.__lt__(other) 
    if op_result is NotImplemented: 
     return op_result 
    return not op_result and self != other 

Also, wenn self < other falsch ist, self != other verwendet wird. Sie haben keine __ne__ Methode definieren, aber Sie haben einen __eq__ bieten und die Standardeinstellung für __ne__ ist dann not self.__eq__(other) zurückzukehren; siehe die object.__ne__() documentation:

standardmäßig __ne__() Delegierten __eq__() und invertiert das Ergebnis, wenn es NotImplemented ist.

Für Ihre Test Currency Instanzen __eq__ ist nicht erforderlich, candyPrice.__gt__(bookPrice) Anrufe candyPrice.__lt__(bookPrice), die für self != other ohne Überprüfung true zurückgibt und damit False zurückgegeben.