'and' (boolean) vs '&' (bitwise) - Why difference in behavior with lists vs numpy arrays?
是什么解释了列表和NumPy数组上布尔运算和按位运算的行为差异?
我对在Python中正确使用
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 26 27 | 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数组的处理方式不同?
在Python中,空的内置对象通常在逻辑上被视为
1 2 3 4 | >>> if [False]: ... print 'True' ... True |
因此,在示例1中,第一个列表为非空,因此在逻辑上为
例如,2不能以位方式有意义地组合列表,因为它们可以包含任意不同的元素。可以按位组合的事物包括:对和错,整数。
相反,NumPy对象支持矢量化计算。也就是说,它们使您可以对多个数据执行相同的操作。
示例3失败,因为NumPy数组(长度> 1)没有真值,因为这可以防止基于矢量的逻辑混淆。
示例4只是一个向量化的位
底线
-
如果您不处理数组并且不执行整数的数学运算,则可能需要
and 。 -
如果您希望合并真值向量,请使用
numpy 和& 。
短路布尔运算符(
1 2 3 4 | something_true and x -> x something_false and x -> something_false something_true or x -> something_true something_false or x -> x |
请注意,返回的是实际操作数的(求值结果),而不是其真值。
定制其行为的唯一方法是覆盖
NumPy数组拒绝该概念:对于它们针对的用例,两个不同的真理概念是相同的:(1)任何元素是否为真,以及(2)所有元素是否为真。由于这两个是完全(且无声地)不兼容的,而且都不是更正确或更普遍的,因此NumPy拒绝猜测,要求您显式使用
关于
首先是非常重要的一点,一切都会随之而来(我希望)。
好。
在普通的Python中,
好。
(是的,它支持更改其元素,并支持迭代和许多其他功能,但这就是类型的含义:它支持某些操作,而不支持其他一些操作。int支持提升为幂,但不支持此功能。让它变得非常特别-这就是一个int的意思。lambda支持调用,但这并没有使其非常特别-这毕竟是lambda的目的:)。
好。
关于
好。
其结果是
好。
想象一下,Python解释" a和b"(这种方式在字面上并不是真的,但是有助于理解)。当涉及到"和"时,它查看刚刚评估的对象(a),并询问:您是真的吗? (不是:您
好。
如果
好。
如果
好。
说所有这些的另一种方式是
好。
现在,用笔和笔坐几分钟,让自己相信,当{a,b}是{True,False}的子集时,它的工作原理与布尔运算符所期望的完全一样。但是,我希望我已经说服了您,它更加通用,并且您将看到,这种方式更加有用。
好。
将这两个放在一起
现在,我希望您理解您的示例1。
好。
第二个示例:
另一方面,
好。
麻木
另一方面:-D,numpy数组很特殊,或者至少是他们想要的。当然,numpy.array只是一个类,它不能以任何方式覆盖
好。
对于
好。
HTH,
好。
好。
范例1:
和运算符就是这样工作的。
x和y =>
如果x为假,则为x,否则为y
因此,换句话说,由于
范例2:
如前所述,
1 2 | >>> 3 & 1 1 |
使用二进制文字(上面的数字相同)更容易看到正在发生的事情:
1 2 | >>> 0b0011 & 0b0001 0b0001 |
按位运算在概念上与布尔(真)运算相似,但是它们仅对位起作用。
所以,给我一些关于我的车的陈述
这两个语句的逻辑"和"为:
(is my car red?) and (does car have wheels?) => logical true of false value
至少对于我的车来说,这两者都是正确的。因此,该语句的整体值在逻辑上是正确的。
这两个语句的按位"和"有点模糊:
(the numeric value of the statement 'my car is red') & (the numeric value of the statement 'my car has wheels') => number
如果python知道如何将语句转换为数值,则它将这样做并计算两个值的按位和。这可能使您相信
示例3和4:
Numpy实现数组的算术运算:
Arithmetic and comparison operations on ndarrays are defined as element-wise operations, and generally yield ndarray objects as results.
但是不会为数组实现逻辑运算,因为您无法在python中重载逻辑运算符。这就是为什么示例三不起作用,但是示例四却不起作用的原因。
因此,回答您的
按位运算用于检查数字的结构(哪些位已设置,哪些位未设置)。这种信息主要用于底层操作系统接口(例如,unix许可位)。大多数python程序都不需要知道这一点。
但是,逻辑运算(
在Python中,如果
1 2 3 4 5 6 7 8 | True and 20 >>> 20 False and 20 >>> False 20 and [] >>> [] |
根本没有为列表定义按位运算符。但是它是为整数定义的-在数字的二进制表示形式上进行操作。考虑16(01000)和31(11111):
1 2 | 16 & 31 >>> 16 |
NumPy不是通灵的,它不知道,你的意思是
例如在逻辑表达式中,
NumPy数组的&运算符的预期行为。
对于第一个示例,基于Django的文档
它将始终返回第二个列表,实际上,非空列表被视为Python的True值,因此python返回"最后一个" True值,因此第二个列表
1 2 3 4 5 6 | 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] |
使用Python列表的操作在列表上进行。
仅当按元素应用时有意义的运算符(例如
Numpy数组支持按元素操作。
这不适用于
1 2 3 4 | if bool(array1): return array2 else: return array1 |
为此,您需要一个很好的