2016-07-23 64 views
0

考慮下面的Python程序:Python的列表.__包含___調用__eq__的順序是什麼?

class Foo(object): 

    def __init__(self, bar): 
     self.bar = bar 

    def __repr__(self): 
     return 'Foo(%r)' % (self.bar,) 

    def __eq__(self, other): 
     print('Foo.__eq__(%r, %r)' % (self, other)) 
     return self.bar == other 

foo1 = Foo('A') 
foo2 = Foo('B') 
assert foo1 not in [foo2] 

在CPython的2.7.11和3.5.1,它打印:

Foo.__eq__(Foo('A'), Foo('B')) 
Foo.__eq__(Foo('B'), 'A') 

但PyPy 5.3.1(2.7)下,它打印:

Foo.__eq__(Foo('B'), Foo('A')) 
Foo.__eq__(Foo('A'), 'B') 

儘管Python 3.5的文檔states即使「如果可能」應該是對稱的,有時卻不是。在這種情況下,參數Foo.__eq__的順序變得重要。

那麼,上面的CPython行爲是一個實現細節,還是它的一部分list的公共接口(意味着PyPy有一個bug)?請解釋你爲什麼這麼認爲。

回答

3

the language reference

對於容器類型,例如列表,元組,集,frozenset,字典,或 collections.deque,表達x in y相當於any(x is e or x == e for e in y)

同一部分中的其他示例顯示了相同測試的相同排序。這表明比較應該是item_maybe_in_list.__eq__(item_actually_in_list),在這種情況下,這可能被認爲是PyPy中的一個錯誤。另外,CPython是參考實現,所以任何差異都會使版本獲勝!

這就是說,你應該提高它與社區,看看他們對此感覺如何。

+0

我應該更徹底地閱讀文檔... –

+0

等等,它說'x == e'必須是'x .__ eq __(e)'? –

+0

@Rawing https://docs.python.org/2/reference/datamodel.html#object.__eq__ –

相關問題