为什么会这样,在python / numpy中:
from numpy import asarray
bools=asarray([False,True])
print(bools)
[False True]
print(1*bools, 0+bools, 0-bools) # False, True are valued as 0, 1
[0 1] [0 1] [ 0 -1]
print(-2*bools, -bools*2) # !? expected same result! :-/
[0 -2] [2 0]
print(-bools) # this is the reason!
[True False]
我认为-bools
返回logical_not(bools)
很奇怪,因为在所有其他情况下,行为是“算术”,而不是“逻辑”。
想要使用布尔数组作为0/1掩码(或“特征函数”)的人被迫使用某种渐开线表达式,例如(0-bools)
或(-1)*bools
,并且很容易招致如果他忘了这件事就会陷入错误。
为什么会如此,以及获得所需行为的最佳方式是什么? (当然评论旁边)
答案 0 :(得分:2)
关于运营商订单和数据类型。
>>> -B
array([ True, False], dtype=bool)
使用numpy时,布尔数组被视为布尔数组。应用于它们的每个操作,将首先尝试维护数据类型。那是方式:
>>> ~B
array([ True, False], dtype=bool)
和
-B
等价的返回其元素的元素否定。但请注意,使用>>> B + 1
array([1, 2])
会抛出警告,因为该函数已弃用。
当您使用以下内容时:
B
1
和boolean
首先在引擎盖下转换为相同的数据类型。在数据类型促销中,numeric
数组始终会转换为B
数组。在上述情况下,int
会投放到>>> B.astype(int) + 1
array([1, 2])
,类似于:
>>> -B * 2
array([2, 0])
在你的例子中:
B
首先,数组-
被运算符>>> -(B * 2)
array([ 0, -2])
否定,然后乘以2.可以通过显式数据转换或添加括号来采用所需的行为,以确保正确的操作顺序:
>>> -B.astype(int) * 2
array([ 0, -2])
或
B.astype(int)
请注意,B.view(np.int8)
可以在没有characters
的数据副本的情况下被替换,因为布尔值由.view
表示,因此有8位,数据可以被视为整数{ {1}}方法,无需转换。
>>> B.view(np.int8)
array([0, 1], dtype=int8)
因此,简而言之,B.view(np.int8)
或B.astype(yourtype)
将始终确保B
是[0,1]
数字数组。
答案 1 :(得分:0)
Numpy数组是同源的 - 所有元素对于给定数组都具有相同的类型,并且数组对象存储的是什么类型。当您使用True
和False
创建数组时,它是一个类型为bool
的数组,运算符就会在数组上运行。因此,在对正常bool
进行逻辑否定的情况下,您会发生逻辑否定,这并不奇怪。当您使用数组进行整数数学运算时,它们将转换为1和0。在你的所有例子中,那些是更多的异常情况,也就是说,它的行为不应该依赖于良好的代码。
正如评论中所建议的那样,如果你想用0和1的数组做数学运算,最好只做一个0和1的数组。但是,根据您对它们的要求,您可能会更好地查看numpy.where()
等函数。