在Python中,说我们“覆盖”内置运算符的行为是否准确?

时间:2017-03-17 17:06:05

标签: python oop operator-overloading operators

“思考Python:如何像计算机科学家一样思考”中,作者说:

  

对于内置类型,有关系运算符(<>==等。)   比较值并确定何时大于,小于,   或等于另一个。对于程序员定义的类型,我们可以覆盖   通过提供名为__lt__的方法,内置运算符的行为,   代表“小于”。

以下是为__lt__实施的Card方法的代码:

 # inside class Card:
    def __lt__(self, other):
        t1 = self.suit, self.rank
        t2 = other.suit, other.rank
        return t1 < t2

但之前没有为__lt__定义Card,那么我们如何覆盖其行为呢?我们在此定义__lt__的新行为,使其与Card个对象一起使用。所以,__lt__仍然适用于数字,字符串等(所有这些都是我所知道的。)

我说错误的是作者(我深深钦佩的作品)不应该使用“覆盖”吗?

1 个答案:

答案 0 :(得分:3)

简答:不,你&#34; 覆盖&#34; __lt__的{​​{1}}。

如果您查看object 上定义的功能:

object()

(列表中有>>> dir(object()) ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

这意味着在'__lt__'的定义中定义了object

__lt__

现在,如果你写一个课程class object: # ... def __lt__(self,value): """Return self<value.""" # base implementation: objects are not comparable in Python 3 return NotImplemented ,你总是从Card继承(即使你没有提到它)。因此,如果您定义自己的object,则会覆盖__lt__定义

换句话说,如果你写:

object.__lt__

class Card: # ... def __lt__(self, other): t1 = self.suit, self.rank t2 = other.suit, other.rank return t1 < t2 方法解析订单(MRO)将是:

Card

这意味着,如果您在>>> Card.__mro__ (<class '__main__.Card'>, <class 'object'>) 对象x.__lt__上致电Card,则会先在x中查找__lt__,但如果找不到Card一,它将object上的后备并在那里寻找__lt__。所以你的__lt__&#34;隐藏&#34;原始__lt__

正如您可以阅读here__lt____le____eq____ne____gt____ge__丰富的比较方法

  

这些是所谓的&#34;丰富的比较&#34;方法。运算符符号和方法名称之间的对应关系如下:x<y调用x.__lt__(y)x<=y调用x.__le__(y)x==y调用x.__eq__(y),{{ 1}}调用x!=yx.__ne__(y)调用x>yx.__gt__(y)调用x>=y

     

富比较方法如果没有实现给定参数对的操作,则可能返回单例x.__ge__(y)。按照惯例,返回NotImplementedFalse以进行成功比较。但是,这些方法可以返回任何值,因此如果在布尔上下文中使用比较运算符(例如,在if语句的条件下),Python将在值上调用True以确定结果是否为true或者是假的。