Обратите внимание, что это не так в Python 3.6:
>>> d = float("nan") #object nan
>>> d
nan
>>> c = {"a": 3, d: 4}
>>> c["a"]
3
>>> c[d]
4
Как я понимаю:
c - это словарь, который содержит 3, связанные с «a», и 4, связанные с nan.
Изменился внутренний взгляд на словарь в Python 3.6, теперь он сравнивает два указателя, и если они указывают на один и тот же объект, они считают, что равенство сохраняется. В противном случае они сравнивают хеш, если хеш отличается, то это не тот же объект. После этого, если необходимо, ключи сравниваются «вручную».
Это означает, что, хотя IEEE754 указывает, что NAN не равен самому себе:
>>> d == d
False
При поиске в словаре сначала учитываются указатели, а поскольку они указывают на один и тот же объект nan, возвращается 4.
Обратите внимание, что:
>>> e = float("nan")
>>> e == d
False
>>> c[e]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: nan
>>> c[d]
4
Таким образом, не каждая нана указывает на 4, поэтому сохраняется какой-то IEEE754. Это было реализовано, потому что соблюдение стандарта, согласно которому nan никогда не равен себе, снижает эффективность более чем игнорирование стандарта. Именно потому, что вы храните в словаре что-то, к чему у вас больше нет доступа в предыдущих версиях.