为什么 "None in numpy.asarray(...)" 会导致未来的警告

Why does "None in numpy.asarray(...)" cause a future warning

未来的警告会在您执行以下操作时发生:

>>> numpy.asarray([1,2,3,None]) == None

目前 return 是 False,但我知道 return 一个包含 [False,False,False,True] 的数组会出现在 Numpy 的未来版本中。

正如所讨论的 on the numpy discussion list 解决此问题的方法是测试 a is None

让我感到困惑的是 in 关键字与一维数组相比列表的这种行为:

>>> None in [1,2,3,None]
True
>>> None in numpy.asarray([1,2,3,None])
__main__:1: FutureWarning: comparison to 'None' will result in an elementwise 
    object comparison in the future
False
>>> 1 in numpy.asarray([1,2,3,None])
True

编辑(见评论)——实际上有两个不同的问题:

  1. 为什么这会导致 FutureWarning - None in numpy.asarray(...) 的未来行为与现在相比会怎样?
  2. 为什么 inlist 的行为不同;我可以测试我的数组是否包含 None 而无需将其转换为列表或使用 for 循环吗?

Numpy 版本是 1.9.1,Python3.4.1

The future warning happens when you do something like this:

numpy.asarray([1,2,3,4]) == None

Which currently returns False, but I understand will return an array containing [False,False,False,True] in a future version of Numpy.

正如我在评论中提到的,您的示例不正确。 numpy 的未来版本将 return [False ,False, False, False],即数组中每个不等于 None 的元素 False。这与当前与其他标量值的逐元素比较的工作方式更加一致,例如:

In [1]: np.array([1, 2, 3, 4]) == 1
Out[1]: array([ True, False, False, False], dtype=bool)

In [2]: np.array(['a', 'b', 'c', 'd']) == 'b'
Out[2]: array([False,  True, False, False], dtype=bool)

What confuses me is this behaviour of the in keyword with a 1D array compared to a list

当您测试 x in y 时,您正在调用 y.__contains__(x)。当 y 是一个列表时,__contains__ 基本上按照以下方式做一些事情:

for item in y:
    if (item is x) or (item == x):
        return True
return False

据我所知,np.ndarray.__contains__(x) 执行的相当于:

if any(y == x):
    return True
else:
    return False

也就是说它首先测试整个数组的元素相等性(y == x 将是一个大小为 y 的布尔数组)。由于在您的情况下您正在测试是否 y == None,这将出于上述原因提高 FutureWarning

在评论中你也想知道为什么

np.nan in np.array([1, 2, 3, np.nan])

returns False,但是

np.nan in [1, 2, 3, np.nan]

returns True。第一部分很容易解释为 np.nan != np.nan (see here for the rationale behind this)。要理解为什么第二种情况 returns True,请记住 list.__contains__() 在检查相等性 (==) 之前首先检查身份 (is)。由于np.nan is np.nan,第二种情况会return True.