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]
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 nan
s, 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.
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]
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 nan
s, 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.