几乎所有使用 IEEE 浮点值的人都曾遇到过 NaN,或“不是数字”。众所周知,NaN 不等于自身。
>>> x = float('nan')
>>> x == x
False
现在,我已经接受了这一点,但有一种奇怪的行为让我难以理解。即,
>>> x in [x]
True
我一直以为
list.__contains__
写的是这样的
def __contains__(self, element):
for x in self:
if element == x:
return True
return False
即,它在内部对相关数据类型使用了
__eq__
。确实如此。如果我用我自己设计的 __eq__
方法定义自定义类,那么我可以验证 Python 在进行包含检查时确实调用了 __eq__
。但是,怎么可能存在一个值 x
(在我们的例子中是 NaN)使得 x == x
为假但 x in [x]
为真?
我们也可以通过自定义
__eq__
观察到相同的行为。
class Example:
def __eq__(self, other):
return False
x = Example()
print(x == x) # False
print(x in [x]) # True
According to the docs 它首先使用
is
运算符来检查是否相等,并且由于 x is x
是 True
,x in [x]
也是 True
:
对于列表、元组、集合、frozenset、字典或collections.deque等容器类型,表达式
等同于x in y
.any(x is e or x == e for e in y)
请注意,身份(
is
)不同于平等(==
)。另请注意,并非所有 NaN 值都由同一个对象表示,因此如果您尝试使用两个不同的 NaN 对象进行测试:
>>> float('nan') in [float('nan')]
False
你会看到不同的结果。