Python3:为什么要自然而然地进行比较?

Python3: why the comparison is naturally made?

在下面的代码中,我在魔术方法 __lt__() 中定义了 '<',如果第一个参数小于第二个参数,它将 return True return 否则为假。

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

然后我在测试程序中用'<'调用了__lt__()。在这种情况下,candyPrice(第一个参数)小于 bookPrice(第二个参数),因此它按预期 returned True。然后,我将这两个值与 class Currency 中未预定义的 '>' 进行比较,但它也按预期 returned False所以我想知道是不是因为已经定义了__lt__(),那么相反的表达式'>'表达式也被隐式定义了?

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

    print (candyPrice < bookPrice)
    print (candyPrice > bookPrice)

您使用了 @total_ordering class 装饰器。这个装饰器显式地为你添加了其他方法

来自@functools.total_ordering documentation

Given a class defining one or more rich comparison ordering methods, this class decorator supplies the rest. This simplifies the effort involved in specifying all of the possible rich comparison operations:

The class must define one of __lt__(), __le__(), __gt__(), or __ge__(). In addition, the class should supply an __eq__() method.

所以即使您没有定义 __gt__ 方法,class 装饰器已经使用您的 __lt__ 方法为您定义了一个方法,连同 __eq__

例如,定义__lt__方法时,__gt__()实现设置为:

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

因此,如果 self < other 为假,则使用 self != other。您没有定义 __ne__ 方法,但您确实提供了 __eq__ 并且 __ne__ 的默认值为 return not self.__eq__(other);请参阅 object.__ne__() documentation:

By default, __ne__() delegates to __eq__() and inverts the result unless it is NotImplemented.

对于您的测试 Currency 个实例 __eq__ 是不需要的,candyPrice.__gt__(bookPrice) 调用 candyPrice.__lt__(bookPrice),return 是正确的,因此 False returned 没有检查 self != other.