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

时间:2019-04-29 14:40:56

标签: python numpy

TLDR: is-comparison可以与Python bool一起使用,而不能与numpy bool_一起使用。还有其他区别吗?


几天前,我遇到了布尔值的一种奇怪行为。当我尝试对这个numpy数组使用is-comparison时:

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 bool,而arr1是由{{ 1}}。所以我检查了他们的行为:

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]

毕竟,我有两个问题:

  1. Out[...]: [False, True]numpy.bool_的共同行为是否还有其他差异? (我知道bool有许多numpy函数和参数,例如numpy.bool_等)
  2. 如何检查numpy数组是否仅包含numpy布尔值而没有Pythonic bool?

(PS:是的,现在,我知道用.T与True / False进行比较是不好的):

  

请勿使用==将布尔值与True或False进行比较。

is
Yes:   if greeting:
No:    if greeting == True:
Worse: if greeting is True:

编辑1:another question中所述,numpy具有自己的 类型。但是,这个问题的细节有些不同:我发现is语句的工作原理有所不同,但是在出现这种差异之前-bool_bool_的共同行为是否还有其他不同?如果是,那到底是什么?

3 个答案:

答案 0 :(得分:2)

变量存在一些混淆,正在发生的是模块与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))

答案 1 :(得分:2)

{
  'cam': 'CA Manager', 
  'control_account': 'W80.11.11.01.LL', 
  'risk_mitigation_scope': 'No', 
  'statement_of_work': 'For setup and maintainance of of the W80 EVMS Tools', 
  'wp_manager': 'cohagan1', 
  'wp_title': 'EVMS Tools', 
  'wp_type': 'Discrete'
}

注意dtype。使用object dtype,数组的元素是Python对象,就像它们在源列表中一样。

在第一种情况下,数组dtype为布尔值。元素表示布尔值,但它们本身不是Python 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) 对象。严格来说,True/False不是Out[119] contain个对象。 np.bool_的类型为Out[119][1],但这是“取消装箱”的结果。这是bool_索引在您请求元素时产生的结果。 (此“拆箱”区别适用于所有非对象dtypes。)

通常,我们不创建ndarray对象,而是选择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测试,而不能满足==测试。

让我们玩一下对象dtype数组:

is

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相同的许多属性/方法。

  • 如果数组dtype为np.array(False),则它不包含Python bool对象。它甚至不包含bool个对象。但是,为这样的数组建立索引将产生一个np.bool_。然后将bool_应用于它会产生一个Python item()

  • 如果数组对象是dtype,则除非您已采取特殊步骤包括bool对象,否则它很可能包含Python bool

答案 2 :(得分:0)

另一个区别是可以在 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.