考虑以下Python程序:
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)?请解释你为什么这么认为。
答案 0 :(得分:3)
对于容器类型,例如list,tuple,set,frozenset,dict或 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是参考实现,所以在任何差异中版本都会赢!
那就是说,你应该和那个社区一起提高它,看看他们对此感觉如何。