Consider a REPL with two tuples, a and b.
>>> type(a), type(b)
(<type 'tuple'>, <type 'tuple'>)
>>> a == b
True
So far, so good. But let's dig deeper...
>>> a[0] == b[0]
False
The tuples are equal, but their contents is not.
>>> a is b
True
In fact, there was only ever one tuple.
What is this madness?
>>> a
(nan,)
Welcome to the float zone.
Many parts of python assume that a is b implies a == b, but floats break this assumption. They also break the assumption that hash(a) == hash(b) implies a == b.
>>> hash(float('nan')) == hash(float('nan'))
True
Dicts handle this pretty elegantly:
>>> n = float('nan')
>>> {n: 1}[n]
1
>>> a = {float('nan'): 1, float('nan'): 2}
>>> a
{nan: 1, nan: 2}