If we make a pathological potato like this:
>>> class Potato:
... def __eq__(self, other):
... return False
... def __hash__(self):
... return random.randint(1, 10000)
...
>>> p = Potato()
>>> p == p
False
We can break sets and dicts this way (note: it's the same even if __eq__
returns True
, it's mucking with the hash that broke them):
>>> p in {p}
False
>>> p in {p: 0}
False
Also len({p: 0, p: 0}) == 2
, and {p: 0}[p]
raises KeyError, basically all mapping related stuff goes out the window, as expected.
But what I didn't expect is that we can't break lists
>>> p in [p]
True
Why is that? It seems that list.__contains__
iterates, but it's first checking identity before checking equality. Since it is not the case that identity implies equality (see for example NaN object), what is the reason for lists short-circuiting on identity comparisons?
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…