Python bool和numpy bool_的行为到底有什么不同?

8oomwypt  于 2022-12-13  发布在  Python
关注(0)|答案(4)|浏览(313)

**TLDR:**is-comparison适用于Python bool,不适用于numpy bool_。是否存在其他差异?

几天前我遇到了一个奇怪的布尔行为。当我试图对这个numpy数组使用is比较时:

arr1 = np.array([1,0,2,0], dtype=bool)
arr1

Out[...]: array([ True, False,  True, False])
  • (这些变量名称是虚构的,与真实的变量名称或产品代码的任何相似之处纯属巧合)*

我看到了这样的结果:

arr1 is True

Out[...]: False

这是合乎逻辑的,因为arr1不是True或False,它是numpy数组。我检查了以下内容:

arr1 == True

Out[...]: array([ True, False,  True, False])

这和预期的一样有效。我提到了这个可爱的行为,但马上就忘记了。第二天我检查了数组元素的真实性:
[elem is False for elem in arr1]
它还给我这个!
Out[...]: [False, False, False, False]
我真的很困惑,因为我记得在Python数组中(我以为问题出在数组行为中):

arr2 = [True, False, True, False]
[elem is False for elem in arr2]

它的工作原理是:
Out[...]: [False, True, False, True]
而且,它还在我的另一个 numpy 数组中工作:

very_cunning_arr = np.array([1, False, 2, False, []])
[elem is False for elem in very_cunning_arr]

Out[...]: [False, True, False, True, False]
当我深入到我的数组中时,我发现very_cunning_arr是由numpy.object构造的,因为有几个非数字元素,所以它包含Python布尔值,而arr1是由numpy.bool_构造的。所以我检查了它们的行为:

numpy_waka = np.bool_(True)
numpy_waka

Out[...]: True

python_waka = True
python_waka

Out[...]: True
[numpy_waka is True, python_waka is True]
而我终于发现了不同之处:
Out[...]: [False, True]
在所有这些之后我有两个问题:

  1. numpy.bool_bool在它们的共同行为中是否有一些其他的差异?(我知道numpy.bool_有许多numpy函数和参数,如.T和其他)
    1.如何检查numpy数组是否只包含numpy布尔值,而不包含Python布尔值?
    (PS:是的,现在我知道用is比较True/False是不好的):
    不要使用==将布尔值与True或False进行比较。
Yes:   if greeting:
No:    if greeting == True:
Worse: if greeting is True:

**Edit 1:**正如在another question中提到的,numpy有自己的bool_类型,但是这个问题的细节有点不同:我发现is-statements的工作方式不同,但在此之前,bool_bool的共同行为是否有其他不同之处?如果有,具体是什么?

mxg2im7a

mxg2im7a1#

In [119]: np.array([1,0,2,0],dtype=bool)                                             
Out[119]: array([ True, False,  True, False])

In [120]: np.array([1, False, 2, False, []])                                         
Out[120]: array([1, False, 2, False, list([])], dtype=object)

注意dtype。对于对象dtype,数组的元素是Python对象,就像它们在源列表中一样。
在第一种情况下,数组的dtype是布尔型的。元素代表布尔值,但它们本身不是Python True/False对象。严格地说,Out[119]不是containnp.bool_对象。Out[119][1]bool_类型。但这是'unboxing'的结果。它是ndarray索引在您请求一个元素时产生的结果。(这种'unboxing'的区别对所有非对象数据类型都是正确的。)
通常我们不创建dtype对象,而更喜欢np.array(True),但要遵循您的示例:

In [124]: np.bool_(True)                                                             
Out[124]: True
In [125]: type(np.bool_(True))                                                       
Out[125]: numpy.bool_
In [126]: np.bool_(True) is True                                                     
Out[126]: False
In [127]: type(True)                                                                 
Out[127]: bool

is是一个严格的测试,不仅是对相等性的测试,还对同一性的测试。不同类的对象不满足is测试。对象可以满足==测试,但不满足is测试。
让我们来看看对象dtype数组:

In [129]: np.array([1, False, 2, np.bool_(False), []])                               
Out[129]: array([1, False, 2, False, list([])], dtype=object)
In [130]: [i is False for i in _]                                                    
Out[130]: [False, True, False, False, False]

Out[129]显示中,两个False对象显示相同,但Out[130]测试显示它们不同。
专注于你的问题。

  • np.bool_(False)是一个独特的对象,但与False不同。正如您所注意到的,它有许多与np.array(False)相同的属性/方法。
  • 如果数组dtype是bool,它就不包含Python bool对象,甚至不包含np.bool_对象,然而索引这样的数组会产生bool_,而将item()应用于它会产生Python bool
  • 如果数组对象是dtype,那么它很可能包含Python bool,除非你已经采取了特殊的步骤来包含bool_对象。
5gfr0r5j

5gfr0r5j2#

变量有些混乱,发生的是模块和python之间的“混乱”,使用isinstance(variable, type)检查它是什么,如果在你的代码中可用。
创建一个bool变量就可以了,python会正确地读取它:

np_bool = np.bool(True)
py_bool = True

print(isinstance(np_bool, bool)) # True
print(isinstance(py_bool, bool)) # True

但是对于列表,情况就不同了,numpy bool列表并不是列表上的bool值,正如你在这个例子中看到的:

# Regular list of int
arr0 = [-2, -1, 0, 1, 2]

# Python list of bool
arr1 = [True, False, True, False]

# Numpy list of bool, from int / bool
arr3_a = np.array([-2, -1, 0, 1, 2], dtype=bool)
arr3_b = np.array([True, False, True, False], dtype=bool)

print(isinstance(arr0[0], int))    # True
print(isinstance(arr1[0], bool))   # True

print(isinstance(arr3_a[0], bool)) # False
print(isinstance(arr3_b[0], bool)) # False

为了使用numpy列表中的变量,需要使用bool()进行转换

arr3_a = np.array([-2, -1, 0, 1, 2], dtype=bool)

x = (bool(arr3_a[0]) is True)
print(isinstance(x, bool)) # True

快速使用示例:

arr3_a = np.array([-2, -1, 0, 1, 2], dtype=bool)

for c in range(0, len(arr3_a)):
    if ( bool(arr3_a[c]) == True ):
        print(("List value {} is True").format(c))
    else:
        print(("List value {} is False").format(c))
r8uurelv

r8uurelv3#

另一个区别是可以在np.bool上自动强制转换为整数,但不能在np.bool_上。
这是必需的,例如here

>>> np.bool(False) - np.bool(True)
-1

>>> np.bool_(False) - np.bool_(True)
TypeError: numpy boolean subtract, the `-` operator, is not supported, use the bitwise_xor, the `^` operator, or the logical_xor function instead.
slmsl1lt

slmsl1lt4#

备忘录

def _test():
    a = np.bool_(True)
    b = np.bool_(True)
    c = np.bool_(False)
    d = np.bool_(False)
    # test_1
    print(a is True)
    print(a is False)
    print(a == True)
    print(a == False)
    print(c is True)
    print(c is False)
    print(c == True)
    print(c == False)
    # test_2
    print(a is b)
    print(a == b)
    print(a and b)
    print(a or b)
    # test_3
    print(a is c)
    print(a == c)
    print(a and c)
    print(a or c)
    # test_4
    print(c is d)
    print(c == d)
    print(c and d)
    print(c or d)
    # test_5
    print(not a)
    print(not c)

测试1:
假假真假
假假假真
测试2:
真真真真
测试3:
假假假真
测试4:
对对错错
测试_5:
假真

相关问题