在运算符中,浮动(" NaN")和np.nan

时间:2017-12-08 20:22:54

标签: python numpy containers nan

我曾经相信Python中的in运算符使用等式检查==来检查某些集合中元素的存在,因此element in some_list大致相当于any(x == element for x in some_list)。例如:

True in [1, 2, 3]
# True because True == 1

1 in [1., 2., 3.]
# also True because 1 == 1.

然而,众所周知NaN不等于它自己。所以我希望float("NaN") in [float("NaN")]False。它确实是False

但是,如果我们使用numpy.nan代替float("NaN"),则情况就大不相同了:

import numpy as np
np.nan in [np.nan, 1, 2]
# True

np.nan == np.nan仍然提供False

怎么可能? np.nanfloat("NaN")之间的区别是什么? in如何处理np.nan

2 个答案:

答案 0 :(得分:28)

要检查项目是否在列表中,Python首先测试对象标识 ,然后仅在对象不同时测试相等性。 1

float("NaN") in [float("NaN")]为False,因为比较中涉及两个不同的 NaN个对象。因此,对于身份的测试返回False,然后对于相等性的测试也返回False,因为NaN != NaN

np.nan in [np.nan, 1, 2]但是为True,因为比较中涉及相同的 NaN对象。对象标识的测试返回True,因此Python立即将该项识别为列在列表中。

对于许多Python的其他内置容器类型(例如元组和集合),__contains__方法(使用in调用)是使用相同的检查实现的。

1 至少在CPython中也是如此。这里的对象标识意味着在同一个内存地址中找到对象:使用contains method for lists执行PyObject_RichCompareBool,它可以在可能更复杂的对象比较之前快速比较对象指针。其他Python实现可能有所不同。

答案 1 :(得分:5)

值得一提的是numpy数组的行为符合预期:

a = np.array((np.nan,))
a[0] in a
# False

主题的变化:

[np.nan]==[np.nan]
# True
[float('nan')]==[float('nan')]
# False
{np.nan: 0}[np.nan]
# 0
{float('nan'): 0}[float('nan')]
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# KeyError: nan

@ AlexRiley的优秀答案涵盖了其他所有内容。