2010-08-27 49 views
48

由于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__函数。只是寻找官方的决策树。

回答

63

a == b表达式调用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 ? 
+9

绝对正确。总而言之,这些测试应该是“return self.value == other.value”。 – 2010-08-28 00:17:26

+0

谢谢Ned!只是一些人:这取决于你在找什么。例如,假设我想:a == 3和a == b都为真(将b.value更改为3)。 – PyProg 2010-08-28 00:48:08

46

当Python2.x看到a == b,它会尝试以下。

  • 如果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 iff ab是相同的对象。

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

注意,小心最后一步:如果没有a也不b重载==,然后a == b是一样的a is b


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

它会帮助别人,希望。

+3

python 3中的顺序是什么? python 2订单在哪里记录? – max 2015-04-13 11:16:12

+0

呃看来python 3文档是不正确的。请参阅http://bugs.python.org/issue4395和补丁以进行澄清。 TLDR:子类仍然首先比较,即使它在rhs上。 – max 2015-04-13 21:15:17

+0

嗨,亲爱的,不错的贴子。你能否解释第一个重点的记录以及为什么要这样设计? – wim 2015-12-31 08:41:36