Python NumPy ndarray内联比较中布尔运算的意外行为
我发现,尝试使用Python NumPy ndarray内联比较中布尔运算的意外行为,python,python-3.x,numpy,multidimensional-array,boolean-operations,Python,Python 3.x,Numpy,Multidimensional Array,Boolean Operations,我发现,尝试使用&,,==,==,=,=等对numpy数组执行多个布尔比较,通常会产生意外的结果,表面上似乎违反了纯python的操作顺序(我在这一点上是错的;例如,True | False==True产生True)。解释这些结果的“规则”是什么?下面是几个例子: 将布尔值ndarray与非布尔值ndarray上的元素比较结果进行比较: In [36]: a = np.array([1,2,3]) In [37]: b = np.array([False, True, False]) In [3
&
,
,==
,==
,=
,=
等对numpy
数组执行多个布尔比较,通常会产生意外的结果,表面上似乎违反了纯python的操作顺序(我在这一点上是错的;例如,True | False==True
产生True
)。解释这些结果的“规则”是什么?下面是几个例子:
将布尔值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)
布尔和非布尔Ndarray上的元素级&
/|
:
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)
我欢迎这种行为的其他示例。我认为您对&
二进制运算符与比较运算符的优先级感到困惑:
>>> 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_和
首先完成(在b
和a
之间),然后将结果与2
进行比较,因为它是一个布尔数组,所以都是False
&
和|
优先级较低的原因是,它们不是逻辑运算符,它表示numpy碰巧用于逻辑的二进制(数学)运算,例如,对于int,我肯定希望&
首先发生:
if 13 & 7 == 5:
不幸的是,numpy不能覆盖逻辑和和或运算符的行为,因为它们的优先级作为逻辑运算符是有意义的,但不幸的是它们不能被覆盖,因此我们只需在执行布尔数组时添加大量括号即可
请注意,有一个but,因为它基本上对numpy来说只是一个很小的方便,同时使所有其他严格的布尔运算变慢。我认为您对&
二进制运算符与比较运算符的优先级感到困惑:
>>> 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_和
首先完成(在b
和a
之间),然后将结果与2
进行比较,因为它是一个布尔数组,所以都是False
&
和|
优先级较低的原因是,它们不是逻辑运算符,它表示numpy碰巧用于逻辑的二进制(数学)运算,例如,对于int,我肯定希望&
首先发生:
if 13 & 7 == 5:
不幸的是,numpy不能覆盖逻辑和和或运算符的行为,因为它们的优先级作为逻辑运算符是有意义的,但不幸的是它们不能被覆盖,因此我们只需在执行布尔数组时添加大量括号即可
请注意,有一个but,因为它基本上对numpy来说只是一个很小的方便,同时使所有其他严格的布尔运算变慢。a>=2&a=(2&a)=(2&a)
是一个布尔数组。但它是Pythonaa>=2&a=(2&a)的一部分
是一个布尔数组。但它是PythonaInnumpy
表达式的一部分,类似于这样的比较,从表面上看,纯Python的操作顺序似乎被违反了-你为什么这么说?&
比=
具有更高的优先级。当numpy使用&
和
作为逻辑时,它们被用作数学运算符,这就是为什么它们的优先级高于比较,我希望5&2==0
首先执行&
运算符。在numpy
表达式中,进行比较,如“表面上似乎违反了纯python的操作顺序”-你为什么这么说?&
比=
具有更高的优先级。虽然numpy使用&
和
作为逻辑,但它们被设计为数学运算符,这就是为什么它们比比较具有更高的优先级,我希望5&2==0
首先执行&
运算符。你说得对,我说得对。这有点与直觉相反,因为LHS项都是布尔值,而RHS项都是非布尔值。这引发了另一个我感到困惑的问题;请看我的新的第二个示例。你能解释一下为什么布尔值结果会被重新转换为整数数组吗?我怀疑人们经常混淆正常情况下和以及&
的优先级thon和
组合比较,而和
是按位的。在numpy中使用和
会产生一个值错误,而和
会按元素操作。@Luke关于转换为int的问题,如果我不得不猜测的话,我会说因为bool
是int
的一个子类,它会看到您在执行和操作两个int数组之间的函数,因此它执行实际的二进制和操作elementwise,然后返回为integers@TadhgMcDonald-Jensen re:PEP提案中,python开发人员不能添加操作符&
或|
,例如,用于逻辑数组与更“逻辑”的比较吗优先级?他们是用@
来实现的,如果我没弄错的话,这只用于矩阵乘法(通常是numpy
中的矩阵乘法)。@LukeDavis idk我没有参与讨论。我猜有三个运算符都表示“和”但是,只有细微的差别是不可取的。无论如何,python的开发人员是基于整个语言做出选择的,numpy的开发人员正在使用他们所拥有的。你是对的,我是。这有点违反直觉,因为LHS项都是布尔的,而RHS项都是非布尔的。这引发了另一个问题,我是同事但是,请看我新的第二个例子。你能解释一下为什么吗