If we make a pathological potato like this:
>>> class Potato:
... def __eq__(self, other):
... return False
... def __hash__(self):
list
, tuple
, etc., does indeed do an identity check before an equality check, and this behavior is motivated by 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
Unfortunately, dict
s, set
s, and friends operate by hashes, so if you mess with those you can indeed effectively break them.
See this issue and this issue for some history.