今天写 Python 代码时遇到一个恶心的 bug ,花了好一会才定位和搞清楚。我的目标是寻找第一个非 NAN 的数的位置(其中 array 是一个 numpy 向量),很自然有下面实现:
import numpy as np
index = next((i for i, x in enumerate(array) if np.isnan(x) is False), None)
结果发现总是返回 None ,也就是 array 数组里全是 NAN。但这是不可能的。最后在 Python 命令里试了一下,才发现 np.isnan(1.0) is False
运行结果都是 False。
chatgpt 的解释很清楚。问:
np.isnan(1) is False
为什么结果是 False ,np.isnan(1)
返回 False ,它 is False 应该是 True 呀。
chatgpt gpt-4 的回答是:
您的理解是正确的,
np.isnan(1)
返回的结果确实是 False。在这里,您可能对 is 和 == 的使用有所混淆。is 和 == 都用于比较两个对象,但它们之间存在一些关键区别:
- is 用于比较两个对象是否相同,即它们是否引用内存中的同一个对象。
- == 用于比较两个对象的值是否相等。
- 在您的例子中,
np.isnan(1)
返回的是一个numpy.bool_
类型的对象,其值为 False。而 Python 中的 False 是一个内置的 bool 类型对象。尽管np.isnan(1)
返回的对象和内置的 False 都表示逻辑上的假,但它们在内存中是不同的对象。因此,当您使用 is 进行比较时,结果为 False ,因为
np.isnan(1)
返回的对象和内置的 False 不是同一个对象。如果您想要比较它们的值是否相等,您应该使用 ==:import numpy as np result = np.isnan(1) == False print(result) # 输出 True
这里,
np.isnan(1) == False
返回 True ,因为np.isnan(1)
的值与 False 的值相等。
其实用==
也不太好, PEP 8 格式检查会提示(但这感觉更像 pep8 的 bug ):
PEP8: E712 comparison to False should be 'if cond is False:' or 'if not cond:'
所以最佳方式应该是:
if not np.isnan(x):
pass
Q. E. D.