为什么将Numpy中的0d数组视为标量?

时间:2019-05-28 01:20:00

标签: python numpy scalar type-promotion

从某种意义上说,它已经有an excellent answer

  

一个人不应该为之苦思。最终对个人的心理健康和长寿更好。

精神健康和长寿固然很好,但是这个人的骄傲又遭受了另一次打击,试图变得狡猾而残酷地被麻木拒绝:

考虑以下我们从一些字节数据开始的地方:

a = np.linspace(0,255,6, dtype=np.uint8)
a
# array([  0,  51, 102, 153, 204, 255], dtype=uint8)

让我们假设我们要添加一些内容并提升类型,因此它不会环绕。对于标量,这不起作用:

b = np.uint16(1)

a + b
# array([  1,  52, 103, 154, 205,   0], dtype=uint8)

但是使用数组,它可以做到:

c = np.ones(1, np.uint16)

a + c
# array([  1,  52, 103, 154, 205, 256], dtype=uint16)

所以我想让我们做一个数组。

b[...]
# array(1, dtype=uint16)
np.isscalar(b[...])
# False

但是,las:

a + b[...]
# array([  1,  52, 103, 154, 205,   0], dtype=uint8)

为什么这个0d数组在这里表现像标量?

1 个答案:

答案 0 :(得分:2)

https://docs.scipy.org/doc/numpy/reference/ufuncs.html#casting-rules

最后一段:

  

混合标量数组操作使用一组不同的强制转换规则,这些规则确保标量不能“上载”数组,除非标量具有根本不同的数据类型(即,在数据类型层次结构中的不同层次结构下) )比数组。此规则使您可以在代码中使用标量常量(作为Python类型,在ufunc中进行相应地解释),而不必担心标量常量的精度是否会导致大型(小型精度)数组上的转换。

我的意思是以下表达式具有相同的作用:

In [56]: np.add(a,1)                                                                 
Out[56]: array([  1,  52, 103, 154, 205,   0], dtype=uint8)
In [57]: np.add(a,np.array(1))                                                       
Out[57]: array([  1,  52, 103, 154, 205,   0], dtype=uint8)

要做到这一点,0d不能“向上转换”。但是列表的行为类似于一维数组,并且会“上传”

In [60]: np.add(a,[1])                                                               
Out[60]: array([  1,  52, 103, 154, 205, 256])
In [61]: np.add(a,np.array([1]))                                                     
Out[61]: array([  1,  52, 103, 154, 205, 256])

https://docs.scipy.org/doc/numpy/reference/arrays.scalars.html

数组标量包括np.uint8(1)等。

  

数组标量对象的数组优先级为NPY_SCALAR_PRIORITY(-1,000,000.0)。

In [67]: np.uint8(1).__array_priority__                                              
Out[67]: -1000000.0
In [68]: np.array(1,'uint8').__array_priority__                                      
Out[68]: 0.0
  

数组标量具有与数组完全相同的方法。这些方法的默认行为是在内部将标量转换为等效的0维数组并调用相应的数组方法。

np.isscalar可以:

        (isinstance(num, generic)
        or type(num) in ScalarType
        or isinstance(num, numbers.Number))

np.isscalar建议使用np.ndim(x) == 0。这首先检查一个.ndim属性(0d数组就是这种情况),然后,尝试np.asarray(x).ndim。因此,从这个意义上讲,任何可以制成0d数组的内容都称为“标量”。可能范围太广,因为字典的数量为:npdim({})