假设我输入:
a = uint8(200)
a*2
然后结果是400,并且重铸为uint16类型。
然而:
a = array([200],dtype=uint8)
a*2
,结果是
array([144], dtype=uint8)
乘法以256为模进行,以确保结果保持在一个字节中。
我对"类型"感到困惑。和" dtypes"并且使用一个而不是另一个。如您所见,类型可能会对输出产生显着影响。
例如,我可以创建单个数量的dtype uint8,以便对该数字的操作将以256为模进行吗?或者,我可以创建一个类型(不是dtype)uint8的数组,以便对它的操作产生超出0-255范围的值吗?
答案 0 :(得分:9)
NumPy数组的type
为numpy.ndarray
;这只是Python对象的类型(类似于type("hello")
str
的例子)。
dtype
只定义内存中的字节将如何由标量(即单个数字)或数组解释,以及字节的处理方式(例如int
/ {{1 }})。因此,您不会更改数组或标量的float
,只更改其type
。
如您所见,如果将两个标量相乘,则生成的数据类型是可以转换这两个值的最小“安全”类型。但是,将数组和标量相乘只会返回相同数据类型的数组。函数dtype
的{{3}}清楚地表明特定标量或数组对象的np.inspect_types
何时发生变化:
NumPy中的类型提升与C ++等语言中的规则类似,但略有不同。当使用标量和数组时,数组的类型优先,并考虑标量的实际值。
文档仍在继续:
如果只有标量或标量的最大类别高于数组的最大类别,则数据类型与
dtype
组合以产生返回值。
因此对于promote_types
两个标量,生成的数据类型将是documentation返回的类型:
np.uint8(200) * 2
对于>>> np.promote_types(np.uint8, int)
dtype('int32')
,数组的数据类型优先于标量np.array([200], dtype=np.uint8) * 2
,并返回int
数据类型。
要解决有关在操作期间保留标量np.uint8
的最终问题,您必须限制用于避免NumPy自动dtype
促销的任何其他标量的数据类型:
dtype
当然,替代方法是简单地将单个值包装在NumPy数组中(然后NumPy不会在使用不同>>> np.array([200], dtype=np.uint8) * np.uint8(2)
144
的标量的操作中将其强制转换。)
要在操作期间提升数组的类型,可以先将任何标量包装在数组中:
dtype
答案 1 :(得分:6)
简单,高级的答案是NumPy在Python的类型系统上层叠第二类系统。
当您要求NumPy对象的type
时,您会获得容器的类型 - 类似于numpy.ndarray
。但是,当您要求dtype
时,您将获得元素的(numpy-managed)类型。
>>> from numpy import *
>>> arr = array([1.0, 4.0, 3.14])
>>> type(arr)
<type 'numpy.ndarray'>
>>> arr.dtype
dtype('float64')
有时,与使用默认float
类型时一样,元素数据类型(dtype
)等同于Python类型。但这相当于,不相同:
>>> arr.dtype == float
True
>>> arr.dtype is float
False
在其他情况下,没有等效的Python类型。例如,当您指定uint8
时。这些数据值/类型可以由Python管理,但与C,Rust和其他系统语言不同,&#34;管理直接与机器数据类型对齐的值(如uint8
与&#34;无符号字节&#34;计算)紧密对齐不是Python的常见用例。
因此,重要的是NumPy提供了在其自己的类型系统下运行的数组和矩阵等容器。它提供了一系列非常有用,优化良好的例程来操作这些容器(及其元素)。如果你小心,你可以混合和匹配NumPy和普通的Python计算。
没有Python类型uint8
。有一个名为uint8
的构造函数,在调用时返回NumPy类型:
>>> u = uint8(44)
>>> u
44
>>> u.dtype
dtype('uint8')
>>> type(u)
<type 'numpy.uint8'>
所以&#34;我可以创建一个类型的数组(不是dtype)uint8 ...?&#34;不,你不能。没有这样的动物。
您可以
在不使用NumPy uint8
(a.k.a。NumPy标量值)的情况下,将计算约束为arrays
规则。 E.g:
>>> uint8(44 + 1000)
20
>>> uint8(44) + uint8(1000)
20
但是如果你想计算mod 256的值,它可能更容易使用Python的mod运算符:
>> (44 + 1000) % 256
20
将大于255的数据值驱动到uint8
数据类型中,然后进行算术运算是获得mod-256算法的一种后门方式。如果你不小心,你可能会导致Python升级&#34;你的值为全整数(杀死你的mod-256方案),或触发溢出异常(因为在C和机器语言中效果很好的技巧通常被更高级别的语言标记)。
答案 2 :(得分:3)
numpy数组包含相同类型的元素,因此np.array([200],dtype=uint8)
是一个数组为uint8
的值为的数组。执行np.uint8(200)
时,您没有数组,只有单个值。这会产生巨大的差异。
对阵列执行某些操作时,类型保持不变,无论单个值是否溢出。禁止在数组中自动向上转换,因为整个数组的大小必须改变。只有在用户明确需要时才会这样做。对单个值执行操作时,它可以轻松地进行上传,而不会影响其他值。