2010-08-27 51 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