在“思考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__
仍然适用于数字,字符串等(所有这些都是我所知道的。)
我说错误的是作者(我深深钦佩的作品)不应该使用“覆盖”吗?
答案 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!=y
,x.__ne__(y)
调用x>y
和x.__gt__(y)
调用x>=y
。富比较方法如果没有实现给定参数对的操作,则可能返回单例
x.__ge__(y)
。按照惯例,返回NotImplemented
和False
以进行成功比较。但是,这些方法可以返回任何值,因此如果在布尔上下文中使用比较运算符(例如,在if语句的条件下),Python将在值上调用True
以确定结果是否为true或者是假的。