NaN is weird.

2 min read Original article ↗

Published March 02, 2026

Last week in the Python Discord we had an unusual discussion about a Python oddity. Specifically concerning float('nan'). It turns out that (rather unsurprisingly when you think about it) float('nan') is hashable.


>>> hash(float('nan'))
274121555

If it is hashable you can put it in a set:


>>> set(float('nan') for _ in range(10))
{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan}

But why are there 10 copies of nan in that set??? A set shouldn't contain duplicates but that set obviously does. This comes down to the simple fact that no two instances of nan equal one another:


>>> float('nan') == float('nan')
False

In fact, the same nan doesn't even equal itself!


>>> nan = float('nan')
>>> nan == nan
False
>>> nan is nan
True

Just to make life even more fun, you can use nan as a key in a dictionary:


>>> my_dict = {float('nan'): 1, float('nan'): 2}
>>> my_dict
{nan: 1, nan: 2}

But, of course, you can't actually get to those values by their keys:


>>> my_dict[float('nan')]
Traceback (most recent call last):
  File "", line 1, in 
    my_dict[float('nan')]
    ~~~~~~~^^^^^^^^^^^^^^
KeyError: nan

That is, unless you stored the specific instance of nan as a variable:


>>> my_dict[nan] = 3
>>> my_dict[nan]
3

You can always get the keys from the dictionary and work that way, but who knows if you'll get the nan you're looking for:


>>> my_keys = list(my_dict.keys())
>>> my_dict[my_keys[0]]
1

As a bonus, we can't even get an accurate count of how many times nan appears in an iterable...


>>> from collections import Counter
>>> Counter(float('nan') for _ in range(10))
Counter({nan: 1, nan: 1, nan: 1, nan: 1, nan: 1, nan: 1, nan: 1, nan: 1, nan: 1, nan: 1})

While I can't see myself ever, deliberately, using nan as a dictionary key, it is a fun little Python oddity.