If we make a pathological potato like this:
>>> class Potato:
... def __eq__(self, other):
... return False
... def __hash__(self):
In general, breaking the assumption that identity implies equality can break a variety of things in Python. It is true that NaN breaks this assumption, and thus NaN breaks some things in Python. Discussion can be found in this Python bug. In a pre-release version of Python 3.0, reliance on this assumption was removed, but the resolution of the bug was to put it back in (i.e., make Python 3 give the same behavior as Python 2, in which the identity check shortcut is done). The documentation for Python 3 correctly says:
For container types such as list, tuple, set, frozenset, dict, or collections.deque, the expression
x in y
is equivalent toany(x is e or x == e for e in y)
.
However, it appears the documentation for Python 2 is incorrect, since it says:
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.
You could raise a documentation bug about this if you want, although it is a pretty esoteric issue so I doubt it will be high on anyone's priority list.