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