NumPy ndarray 内联比较中布尔运算的意外行为
Unexpected behavior of boolean operations in NumPy ndarray inline comparisons
我发现尝试使用 &
、|
、==
、>=
对 numpy
ndarray
执行多个布尔比较等经常给出意想不到的结果,表面上似乎违反了纯粹的python操作顺序(我错了;例如,True | False==True
产生 True
)。解释这些结果的 "rules" 或幕后发生的事情是什么?这里有几个例子:
将布尔值 ndarray
与非布尔值 ndarray
的 元素 比较的结果进行比较:
In [36]: a = np.array([1,2,3])
In [37]: b = np.array([False, True, False])
In [38]: b & a==2 # unexpected, with no error raised!
Out[38]: array([False, False, False], dtype=bool)
In [39]: b & (a==2) # enclosing in parentheses resolves this
Out[39]: array([False, True, False], dtype=bool)
布尔和非布尔 ndarrays 上的元素 &
/|
:
In [79]: b = np.array([True,False,True])
In [80]: b & a # comparison is made, then array is re-cast into integers!
Out[80]: array([1, 0, 1])
在两个值内查找数组元素:
In [47]: a>=2 & a<=2 # have seen this in different stackexchange threads
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
In [48]: (a>=2) & a<=2 # similar to behavior in In[38], but instead get *True* boolean array of
Out[48]: array([ True, True, True], dtype=bool)
In [49]: (a>=2) & (a<=2) # expected results
Out[49]: array([False, True, False], dtype=bool)
逻辑&
/|
产生结果不在或[0,1]
中(如果布尔值结果被强制返回 int
).
In [90]: a & 2
Out[90]: array([0, 2, 2])
我欢迎更多这种行为的例子。
我认为您对 & |
二元运算符与比较运算符的优先级感到困惑:
>>> import dis
>>> dis.dis("b & a==2")
1 0 LOAD_NAME 0 (b)
2 LOAD_NAME 1 (a)
4 BINARY_AND
6 LOAD_CONST 0 (2)
8 COMPARE_OP 2 (==)
10 RETURN_VALUE
你可以在这里看到 BINARY_AND
首先完成(在 b
和 a
之间)然后将结果与 2
进行比较,因为它是一个布尔值数组,全是False
&
和 |
具有较低优先级的原因是因为它们不是逻辑运算符,它代表 numpy 恰好用于逻辑的二进制(数学?)运算,例如对于整数,我肯定希望 &
首先发生:
if 13 & 7 == 5:
不幸的是,numpy 不能覆盖逻辑 and
和 or
运算符的行为,因为它们的优先级作为逻辑运算符是有意义的,但不幸的是,它们不能被覆盖,所以我们只需要生活意志在做布尔数组时添加很多括号。
请注意,有一个 proposal to allow and or
to be overloaded but was not passed,因为基本上它对 numpy 来说只是一个很小的便利,同时会使所有其他严格的布尔运算变慢。
a>=2 & a<=2
被评估为 a>=(2 & a)<=2
() 部分的计算结果为 array([0, 0, 2], dtype=int32)
a>=(2 & a)
是一个布尔数组。但它是 Python a<x<b
表达式的一部分,它在内部使用短路。也就是说,它评估 a<x
并根据其值实际上可能会跳过 <b
部分。类似于 True if a<x else x<b
.
熟悉的 ValueError ambiguous
出现在标量 Python 布尔上下文中使用布尔数组时。
我发现尝试使用 &
、|
、==
、>=
对 numpy
ndarray
执行多个布尔比较等经常给出意想不到的结果,表面上似乎违反了纯粹的python操作顺序(我错了;例如,True | False==True
产生 True
)。解释这些结果的 "rules" 或幕后发生的事情是什么?这里有几个例子:
将布尔值
ndarray
与非布尔值ndarray
的 元素 比较的结果进行比较:In [36]: a = np.array([1,2,3]) In [37]: b = np.array([False, True, False]) In [38]: b & a==2 # unexpected, with no error raised! Out[38]: array([False, False, False], dtype=bool) In [39]: b & (a==2) # enclosing in parentheses resolves this Out[39]: array([False, True, False], dtype=bool)
布尔和非布尔 ndarrays 上的元素
&
/|
:In [79]: b = np.array([True,False,True]) In [80]: b & a # comparison is made, then array is re-cast into integers! Out[80]: array([1, 0, 1])
在两个值内查找数组元素:
In [47]: a>=2 & a<=2 # have seen this in different stackexchange threads ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() In [48]: (a>=2) & a<=2 # similar to behavior in In[38], but instead get *True* boolean array of Out[48]: array([ True, True, True], dtype=bool) In [49]: (a>=2) & (a<=2) # expected results Out[49]: array([False, True, False], dtype=bool)
逻辑
&
/|
产生结果不在或[0,1]
中(如果布尔值结果被强制返回int
).In [90]: a & 2 Out[90]: array([0, 2, 2])
我欢迎更多这种行为的例子。
我认为您对 & |
二元运算符与比较运算符的优先级感到困惑:
>>> import dis
>>> dis.dis("b & a==2")
1 0 LOAD_NAME 0 (b)
2 LOAD_NAME 1 (a)
4 BINARY_AND
6 LOAD_CONST 0 (2)
8 COMPARE_OP 2 (==)
10 RETURN_VALUE
你可以在这里看到 BINARY_AND
首先完成(在 b
和 a
之间)然后将结果与 2
进行比较,因为它是一个布尔值数组,全是False
&
和 |
具有较低优先级的原因是因为它们不是逻辑运算符,它代表 numpy 恰好用于逻辑的二进制(数学?)运算,例如对于整数,我肯定希望 &
首先发生:
if 13 & 7 == 5:
不幸的是,numpy 不能覆盖逻辑 and
和 or
运算符的行为,因为它们的优先级作为逻辑运算符是有意义的,但不幸的是,它们不能被覆盖,所以我们只需要生活意志在做布尔数组时添加很多括号。
请注意,有一个 proposal to allow and or
to be overloaded but was not passed,因为基本上它对 numpy 来说只是一个很小的便利,同时会使所有其他严格的布尔运算变慢。
a>=2 & a<=2
被评估为 a>=(2 & a)<=2
() 部分的计算结果为 array([0, 0, 2], dtype=int32)
a>=(2 & a)
是一个布尔数组。但它是 Python a<x<b
表达式的一部分,它在内部使用短路。也就是说,它评估 a<x
并根据其值实际上可能会跳过 <b
部分。类似于 True if a<x else x<b
.
熟悉的 ValueError ambiguous
出现在标量 Python 布尔上下文中使用布尔数组时。