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

Question:

While the first part of the question (which is in the title) has been answered a few times before (i.e., Why is NaN not equal to NaN?), I don’t see why the second piece works the way it does (inspired by this question How to Check list containing NaN)?

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]
Asked By: sashkello

||

Answers:

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.

Answered By: DSM
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.