如果我们做这样一个病态的土豆:
>>> class Potato:
... def __eq__(self, other):
... return False
... def __hash__(self):
... return random.randint(1, 10000)
...
>>> p = Potato()
>>> p == p
False
我们可以这样分解集合和dict(注意:即使__eq__
返回{
而且len({p: 0, p: 0}) == 2
,并且{p: 0}[p]
也会引发KeyError,基本上所有与映射相关的东西都会如预期那样从窗口中消失。在
但我没想到的是我们不能打破名单
>>> p in [p]
True
为什么?似乎list.__contains__
会迭代,但在检查相等性之前,它首先是checking identity。既然身份并不意味着相等(例如,请参见NaN object),那么在身份比较中列表短路的原因是什么?在
list
,tuple
等,确实在等式检查之前执行身份检查,这种行为是由these invariants引起的:不幸的是,
dict
s、set
s和朋友都是通过散列操作的,所以如果你搞乱了这些,你确实可以有效地破坏它们。在请参见this issue和this issue了解一些历史记录。在
一般来说,打破身份意味着相等的假设可能会破坏Python中的各种事情。的确,NaN打破了这个假设,因此NaN打破了Python中的一些东西。讨论可以在this Python bug中找到。在python3.0的预发行版本中,不再依赖于这个假设,但是解决这个错误的方法是将它放回原位(即,让python3提供与python2相同的行为,在python2中,身份检查快捷方式已经完成)。python3的documentation正确地表示:
但是,Python 2的文档似乎不正确,因为它说:
如果你愿意的话,你可以提出一个文档错误,尽管这是一个相当深奥的问题,所以我怀疑它是否会在任何人的优先权列表中占据重要位置。在
相关问题 更多 >
编程相关推荐