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 == bexpression式调用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) ,如果ab是同一个对象,则为True

如果任何特殊的方法返回NotImplemented ,Python的行为就像该方法不存在一样。

注意最后一步要小心:如果ab都不重载== ,那么a == ba == b是相同a is b


https://eev.ee/blog/2012/03/24/python-faq-equality/

希望这会帮助别人。