之所以有效,是因为int.__eq__(<something>) 返回NotImplemented,发生这种情况时会调用other.__eq__(self),这就是这里返回True 和False 的原因。
演示:
class Derived(int):
def __eq__(self, other):
print self, other
print int.__eq__(other)
print other.__eq__(self)
return int.__eq__(other)
>>> Derived(12) == 12.0
12 12.0
NotImplemented
True
True
>>> Derived(12) == 13.0
12 13.0
NotImplemented
False
False
来自NotImplemented
的文档:
二进制特殊方法应返回的特殊值
(例如__eq__()、__lt__()、__add__()、__rsub__() 等)到
表示该操作未针对
其他类型;可以由就地二进制特殊方法返回
(例如__imul__()、__iand__() 等)用于相同目的。它的
真值是真的。
注意当NotImplemented 返回时,解释器会尝试
其他类型的反射操作,或其他一些回退,
取决于运营商。如果所有尝试的操作都返回
NotImplemented,解释器将引发适当的异常。
当__eq__ 都返回NotImplemented 时会发生什么?
Python 2 和 3 中的行为不同。
在 Python 2 中,它首先回退到 __cmp__ 方法,整数具有 __cmp__ method in Python 2。它已在 Python 3 中删除。
根据 Python 2 文档,如果没有找到任何东西,它最终会退回到身份比较:
如果没有定义__cmp__()、__eq__()或__ne__()操作,类
实例按对象标识(“地址”)进行比较
class Derived(int):
def __eq__(self, other):
print ("Inside __eq__")
return NotImplemented
def __cmp__(self, other):
print ("Inside __cmp__ finally")
return True
>>> Derived(12) == Derived(12)
Inside __eq__
Inside __eq__
Inside __cmp__ finally
False
不要定义一个没有定义方法的类:
class Derived(object):
pass
>>> Derived() == Derived()
False
>>> d = Derived()
>>> d == d # Same objects.
True
Python 3 不再有 __cmp__ 方法,但它现在似乎正在回归身份。而且似乎也没有记录。
# Python 3.5
>>> Derived() == Derived()
False
>>> d = Derived()
>>> d == d
True