How is __eq__ handled in Python and in what order?
由于python不提供其比较运算符的左/右版本,它如何决定调用哪个函数?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class A(object): def __eq__(self, other): print"A __eq__ called" return self.value == other class B(object): def __eq__(self, other): print"B __eq__ called" return self.value == other >>> a = A() >>> a.value = 3 >>> b = B() >>> b.value = 4 >>> a == b "A __eq__ called" "B __eq__ called" False |
这似乎调用了两个
如果修改代码以显示正在比较的值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class A(object): def __eq__(self, other): print("A __eq__ called: %r == %r ?" % (self, other)) return self.value == other class B(object): def __eq__(self, other): print("B __eq__ called: %r == %r ?" % (self, other)) return self.value == other a = A() a.value = 3 b = B() b.value = 4 a == b |
它将打印:
1 2 | A __eq__ called: <__main__.A object at 0x013BA070> == <__main__.B object at 0x013BA090> ? B __eq__ called: <__main__.B object at 0x013BA090> == 3 ? |
当python2.x看到
- 如果
type(b) 是一个新的类,而type(b) 是type(a) 的一个子类,而type(b) 已经覆盖了__eq__ ,则结果为b.__eq__(a) 。 - 如果
type(a) 已经覆盖__eq__ (即type(a).__eq__ 不是object.__eq__ ,则结果为a.__eq__(b) 。 - 如果
type(b) 已覆盖__eq__ ,则结果为b.__eq__(a) 。 - 如果以上都不是这种情况,那么python会重复寻找
__cmp__ 的过程。如果它存在,当它返回zero 时,对象是相等的。 - 作为最后的回退,python调用
object.__eq__(a, b) ,即True iffa 和b 是同一个对象。
如果任何一个特殊的方法返回
注意最后一步:如果
来自https://eev.ee/blog/2012/03/24/python-faq-equality/