Can anyone explain the following behaviour to me?
>>> import numpy as np
>>> {np.nan: 5}[np.nan]
5
>>> {float64(np.nan): 5}[float64(np.nan)]
KeyError: nan
Why does it work in the first case, but not in the second?
Additionally, I found that the following DOES work:
>>> a ={a: 5}[a]
float64(np.nan)
The problem here is that NaN is not equal to itself, as defined in the IEEE standard for floating point numbers:
When a dictionary looks up a key, it roughly does this:
Compute the hash of the key to be looked up.
For each key in the dict with the same hash, check if it matches the key to be looked up. This check consists of
a. Checking for object identity: If the key in the dictionary and the key to be looked up are the same object as indicated by the
isoperator, the key was found.b. If the first check failed, check for equality using the
__eq__operator.The first example succeeds, since
np.nanandnp.nanare the same object, so it does not matter they don’t compare equal:In the second case,
np.float64(np.nan)andnp.float64(np.nan)are not the same object — the two constructor calls create two distinct objects:Since the objects also do not compare equal, the dictionary concludes the key is not found and throws a
KeyError.You can even do this:
In conclusion, it seems a saner idea to avoid NaN as a dictionary key.