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)
    是一个布尔数组。但它是Python
    a
    a>=2&a=(2&a)的一部分
    是一个布尔数组。但它是Python
    aIn
    numpy
    表达式的一部分,类似于
    这样的比较,从表面上看,纯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项都是非布尔的。这引发了另一个问题,我是同事但是,请看我新的第二个例子。你能解释一下为什么吗