I just want to figure out the logic behind these results:
>>>nan = float('nan')
>>>nan == nan
False
# I understand that this is because the __eq__ method is defined this way
>>>nan in [nan]
True
# This is because the __contains__ method for list is defined to compare the identity first then the content?
But in both cases I think behind the scene the function PyObject_RichCompareBool
is called right? Why there is a difference? Shouldn't they have the same behaviour?
==
never callsPyObject_RichCompareBool
on the float objects directly, floats have their ownrich_compare
method(called for__eq__
) that may or may not callPyObject_RichCompareBool
depending on the the arguments passed to it.On the other hand the
list_contains
directly callsPyObject_RichCompareBool
on the items hence you get True in the second case.Note that this is true only for CPython, PyPy's
list.__contains__
method only seems to be comparing the items by calling their__eq__
method:You are right in saying that
PyObject_RichCompareBool
is called, see thelist_contains
function inlistobject.c
.The docs say that:
However that does not appear to be entirely correct.
In the cpython source we have this part:
in this case since the objects are the same, we have equality.
Mathematically, comparing infinity to infinity does not make sense. Thats why equality is not defined for
nan
.For the case
nan in [nan]
, immutable variables are referenced. But be careful::In the first case the immutable variable is referenced. In the second one, two different floats are created and compared.