使一个对象x使“x in[x]”返回Fals

2024-10-01 22:38:42 发布

您现在位置:Python中文网/ 问答频道 /正文

如果我们做这样一个病态的土豆:

>>> class Potato:
...     def __eq__(self, other):
...         return False
...     def __hash__(self):
...         return random.randint(1, 10000)
... 
>>> p = Potato()
>>> p == p
False

我们可以这样分解集合和dict(注意:即使__eq__返回{}也是一样的,这是用散列来破坏它们):

^{pr2}$

而且len({p: 0, p: 0}) == 2,并且{p: 0}[p]也会引发KeyError,基本上所有与映射相关的东西都会如预期那样从窗口中消失。在

但我没想到的是我们不能打破名单

>>> p in [p]
True

为什么?似乎list.__contains__会迭代,但在检查相等性之前,它首先是checking identity。既然身份并不意味着相等(例如,请参见NaN object),那么在身份比较中列表短路的原因是什么?在


Tags: selffalsereturndef身份randomhashdict
2条回答

listtuple等,确实在等式检查之前执行身份检查,这种行为是由these invariants引起的:

assert a in [a]
assert a in (a,)
assert [a].count(a) == 1
for a in container:
    assert a in container    # this should ALWAYS be true

不幸的是,dicts、sets和朋友都是通过散列操作的,所以如果你搞乱了这些,你确实可以有效地破坏它们。在

请参见this issuethis issue了解一些历史记录。在

一般来说,打破身份意味着相等的假设可能会破坏Python中的各种事情。的确,NaN打破了这个假设,因此NaN打破了Python中的一些东西。讨论可以在this Python bug中找到。在python3.0的预发行版本中,不再依赖于这个假设,但是解决这个错误的方法是将它放回原位(即,让python3提供与python2相同的行为,在python2中,身份检查快捷方式已经完成)。python3的documentation正确地表示:

For container types such as list, tuple, set, frozenset, dict, or collections.deque, the expression x in y is equivalent to any(x is e or x == e for e in y).

但是,Python 2的文档似乎不正确,因为它说:

For the list and tuple types, x in y is true if and only if there exists an index i such that x == y[i] is true.

如果你愿意的话,你可以提出一个文档错误,尽管这是一个相当深奥的问题,所以我怀疑它是否会在任何人的优先权列表中占据重要位置。在

相关问题 更多 >

    热门问题