Python ';和';(布尔)vs'&';(按位)-为什么列表与numpy数组的行为有所不同?
是什么解释了列表和NumPy数组上布尔运算和按位运算的行为差异? 我对Python中Python ';和';(布尔)vs'&';(按位)-为什么列表与numpy数组的行为有所不同?,python,numpy,bit-manipulation,boolean-expression,ampersand,Python,Numpy,Bit Manipulation,Boolean Expression,Ampersand,是什么解释了列表和NumPy数组上布尔运算和按位运算的行为差异? 我对Python中&与和的正确使用感到困惑,如以下示例所示 mylist1 = [True, True, True, False, True] mylist2 = [False, True, False, True, False] >>> len(mylist1) == len(mylist2) True # ---- Example 1 ---- >>> mylist1 and m
&
与和
的正确使用感到困惑,如以下示例所示
mylist1 = [True, True, True, False, True]
mylist2 = [False, True, False, True, False]
>>> len(mylist1) == len(mylist2)
True
# ---- Example 1 ----
>>> mylist1 and mylist2
[False, True, False, True, False]
# I would have expected [False, True, False, False, False]
# ---- Example 2 ----
>>> mylist1 & mylist2
TypeError: unsupported operand type(s) for &: 'list' and 'list'
# Why not just like example 1?
>>> import numpy as np
# ---- Example 3 ----
>>> np.array(mylist1) and np.array(mylist2)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
# Why not just like Example 4?
# ---- Example 4 ----
>>> np.array(mylist1) & np.array(mylist2)
array([False, True, False, False, False], dtype=bool)
# This is the output I was expecting!
帮助我理解了这是一个布尔运算,但却是一个位运算
为了更好地理解这个概念,我读了很多书,但我很难用这些信息来理解我上面的4个例子
mylist1 = [True, True, True, False, True]
mylist2 = [False, True, False, True, False]
>>> len(mylist1) == len(mylist2)
True
# ---- Example 1 ----
>>> mylist1 and mylist2
[False, True, False, True, False]
# I would have expected [False, True, False, False, False]
# ---- Example 2 ----
>>> mylist1 & mylist2
TypeError: unsupported operand type(s) for &: 'list' and 'list'
# Why not just like example 1?
>>> import numpy as np
# ---- Example 3 ----
>>> np.array(mylist1) and np.array(mylist2)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
# Why not just like Example 4?
# ---- Example 4 ----
>>> np.array(mylist1) & np.array(mylist2)
array([False, True, False, False, False], dtype=bool)
# This is the output I was expecting!
示例4引导我获得了所需的输出,因此这很好,但我仍然不清楚何时/如何/为什么应该使用和与&
。为什么列表和NumPy数组在使用这些运算符时表现不同
有人能帮我理解布尔运算和按位运算之间的区别,解释为什么它们处理列表和NumPy数组的方式不同吗?
在Python中,X和Y
的表达式返回Y
,假设bool(X)=True
或X
或Y
中的任何一个计算为False,例如:
True and 20
>>> 20
False and 20
>>> False
20 and []
>>> []
只是没有为列表定义按位运算符。但它是为整数定义的——在数字的二进制表示上进行运算。考虑16(01000)和31(11111):
NumPy不是通灵者,它不知道你是不是这个意思
e、 g.[False,False]
在逻辑表达式中应等于True
。在这种情况下,它覆盖了标准的Python行为,即:“任何len(collection)==0的空集合都是False
”
可能是NumPy阵列的&operator的预期行为
和
测试这两个表达式在逻辑上是否都是True
,而和(与True
/False
值一起使用时)测试这两个表达式是否都是True
在Python中,空的内置对象通常在逻辑上被视为False
,而非空的内置对象在逻辑上被视为True
。这有助于实现一个常见用例,即如果列表为空,则需要执行某些操作,如果列表为空,则需要执行其他操作。注意,这意味着列表[False]在逻辑上是True
:
>>> if [False]:
... print 'True'
...
True
因此,在示例1中,第一个列表是非空的,因此逻辑上True
,因此和
的真值与第二个列表的真值相同。(在我们的例子中,第二个列表是非空的,因此在逻辑上是True
,但是识别它需要一个不必要的计算步骤。)
例如,列表不能以位方式进行有意义的组合,因为它们可以包含任意元素。可以按位组合的内容包括:真与假、整数
相比之下,NumPy对象支持矢量化计算。也就是说,它们允许您对多个数据段执行相同的操作
示例3失败,因为NumPy数组(长度>1)没有真值,因为这样可以防止基于向量的逻辑混淆
示例4只是一个矢量化位和操作
底线
- 如果不处理数组,也不执行整数的数学运算,则可能需要
和
- 如果有要组合的真值向量,请将
numpy
与&
一起使用
短路布尔运算符(
和
、或
)不能被重写,因为如果不引入新的语言功能或牺牲短路,就没有令人满意的方法来实现这一点。您可能知道,也可能不知道,它们计算第一个操作数的真值,并根据该值计算并返回第二个参数,或者不计算第二个参数并返回第一个参数:
something_true and x -> x
something_false and x -> something_false
something_true or x -> something_true
something_false or x -> x
请注意,返回的是实际操作数(计算结果),而不是其真值
自定义其行为的唯一方法是重写\uuuuu nonzero\uuuuu
(在Python3中重命名为\uuuuuuu bool\uuuuuu
),这样可以影响返回的操作数,但不能返回其他操作数。列表(和其他集合)在包含任何内容时定义为“真实”,在为空时定义为“虚假”
NumPy数组拒绝这个概念:对于它们所针对的用例,有两种不同的真理概念是常见的:(1)任何元素是否为真,以及(2)所有元素是否为真。由于这两种方法完全不兼容,而且都不正确或更常见,NumPy拒绝猜测,并要求您显式使用.any()
或.all()
&
和|
(顺便说一句,不是
)可以完全覆盖,因为它们不会短路。当被重写时,它们可以返回任何内容,而NumPy很好地利用了这一点来执行元素级操作,就像它们对几乎任何其他标量操作所做的那样。另一方面,列表不跨元素广播操作。正如mylist1-mylist2
没有任何意义,mylist1+mylist2
意味着完全不同的东西一样,列表没有&
操作符。使用Python列表的操作在列表上操作list1和list2
将检查list1
是否为空,如果为空则返回list1
,如果为空则返回list2
list1+list2
将list2
附加到list1
,因此您将获得一个包含len(list1)+len(list2)
元素的新列表
仅在应用元素级时才有意义的运算符(如&
)会引发类型错误
,因为如果不循环元素,则不支持元素级操作
Numpy阵列支持按元素操作
if bool(array1):
return array2
else:
return array1
>>> 3 & 1
1
>>> 0b0011 & 0b0001
0b0001
In [74]: mylist1 = [False]
In [75]: mylist2 = [False, True, False, True, False]
In [76]: mylist1 and mylist2
Out[76]: [False, True, False, True, False]
In [77]: mylist2 and mylist1
Out[77]: [False]
array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20],
[21, 22, 23, 24, 25]])
np.sum(mat) ## --> gives 325
sum(mat) ## --> gives array([55, 60, 65, 70, 75])