Why in numpy `nan == nan` is False while nan in [nan] is True?

PythonNumpyNan

Python Problem Overview


While the first part of the question (which is in the title) has been answered a few times before (i.e., https://stackoverflow.com/questions/10034149/why-is-nan-not-equal-to-nan), I don't see why the second piece works the way it does (inspired by this question https://stackoverflow.com/questions/20319813/how-to-check-list-containing-nan#comment30324111_20319813)?

Namely:

>> nan == nan
False

>> nan in [nan]
True

An explanatory addendum to the question considering the answer from @DSM. So, why float("nan") is behaving differently from nan? Shouldn't it evaluate again to simple nan and why interpreter behaves this way?

>> x = float("nan")
>> y = nan
>> x
nan
>> y
nan
>> x is nan, x is float("nan"), y is nan
(False, False, True)

Basically, it refers to same generic nan in the first case, but creates separate object in the second:

>> nans = [nan for i in range(2)]
>> map(id, nans)
[190459300, 190459300]
>> nans = [float("nan") for i in range(2)]
>> map(id, nans)
[190459300, 190459301]

Python Solutions


Solution 1 - Python

nan not being equal to nan is part of the definition of nan, so that part's easy.

As for nan in [nan] being True, that's because identity is tested before equality for containment in lists. You're comparing the same two objects.

If you tried the same thing with two different nans, you'd get False:

>>> nans = [float("nan") for i in range(2)]
>>> map(id, nans)
[190459300, 190459284]
>>> nans
[nan, nan]
>>> nans[0] is nans[1]
False
>>> nans[0] in nans
True
>>> nans[0] in nans[1:]
False

Your addendum doesn't really have much to do with nan, that's simply how Python works. Once you understand that float("nan") is under no obligation to return some nan singleton, and that y = x doesn't make a copy of x but instead binds the name y to the object named by x, there's nothing left to get.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionsashkelloView Question on Stackoverflow
Solution 1 - PythonDSMView Answer on Stackoverflow