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}

Planet Python