Python中如何处理__eq__以什么顺序?
由于Python不提供比较运算符的左/右版本,它如何决定调用哪个函数?
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
这似乎同时调用__eq__
函数。 只是在寻找官方的决策树。
a == b
expression式调用A.__eq__
,因为它存在。 它的代码包括self.value == other
。 由于int不知道如何将自己与B进行比较,Python会尝试调用B.__eq__
来查看它是否知道如何将自身与int进行比较。
如果您修改代码以显示正在比较哪些值:
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
它会打印:
A __eq__ called: <__main__.A object at 0x013BA070> == <__main__.B object at 0x013BA090> ? B __eq__ called: <__main__.B object at 0x013BA090> == 3 ?
当Python2.x看到a == b
,它会尝试以下操作。
- 如果
type(b)
是一个新风格的类,并且type(b)
是type(b)
的子类,并且type(b)
已经被覆盖__eq__
,那么结果是b.__eq__(a)
。 - 如果
type(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)
,如果a
和b
是同一个对象,则为True
。
如果任何特殊的方法返回NotImplemented
,Python的行为就像该方法不存在一样。
注意最后一步要小心:如果a
和b
都不重载==
,那么a == b
与a == b
是相同a is b
。
从https://eev.ee/blog/2012/03/24/python-faq-equality/
希望这会帮助别人。