数据类型对象 ( dtype )#

数据类型对象( numpy.dtype 类的实例)描述了如何解释与数组项对应的固定大小内存块中的字节.它描述了数据的以下几个方面:

  1. 数据的类型(整数,浮点数,Python对象等)

  2. 数据的大小(例如,整数有多少字节)

  3. 数据的字节序( little-endianbig-endian )

  4. 如果数据类型是 structured data type ,即其他数据类型的聚合(例如,描述由整数和浮点数组成的数组项),

    1. 结构的“ fields ”的名称是什么,通过这些名称可以 accessed ,

    2. 每个 field 的数据类型是什么,以及

    3. 每个字段占用内存块的哪一部分.

  5. 如果数据类型是子数组,则它的形状和数据类型是什么.

为了描述标量数据的类型,NumPy 中有几种 built-in scalar types ,用于表示不同精度的整数,浮点数等.从数组中提取的项目(例如,通过索引)将是一个 Python 对象,其类型是与数组数据类型关联的标量类型.

请注意,标量类型不是 dtype 对象,即使它们可以在 NumPy 中需要数据类型规范的任何地方使用.

结构化数据类型是通过创建 field 包含其他数据类型的数据类型来形成的.每个字段都有一个名称,可以通过该名称 accessed .父数据类型应具有足够的大小以包含其所有字段;父类型几乎总是基于 void 类型,该类型允许任意项目大小.结构化数据类型还可以在其字段中包含嵌套的结构化子数组数据类型.

最后,一种数据类型可以描述本身是另一种数据类型项目的数组的项目.但是,这些子数组必须具有固定的大小.

如果使用描述子数组的数据类型创建数组,则在创建数组时,子数组的维度将附加到数组的形状.结构化类型字段中的子数组行为有所不同,请参见 字段访问 .

子数组始终具有 C 连续的内存布局.

示例

一个包含 32 位大端整数的简单数据类型:(有关构造的详细信息,请参见 指定和构造数据类型 )

>>> import numpy as np
>>> dt = np.dtype('>i4')
>>> dt.byteorder
'>'
>>> dt.itemsize
4
>>> dt.name
'int32'
>>> dt.type is np.int32
True

相应的数组标量类型为 int32 .

示例

一个结构化的数据类型,包含一个 16 字符的字符串(在 ‘name’ 字段中)和一个包含两个 64 位浮点数的子数组(在 ‘grades’ 字段中):

>>> import numpy as np
>>> dt = np.dtype([('name', np.str_, 16), ('grades', np.float64, (2,))])
>>> dt['name']
dtype('<U16')
>>> dt['grades']
dtype(('<f8', (2,)))

此数据类型数组的项目被包装在 array scalar 类型中,该类型也具有两个字段:

>>> import numpy as np
>>> x = np.array([('Sarah', (8.0, 7.0)), ('John', (6.0, 7.0))], dtype=dt)
>>> x[1]
('John', [6., 7.])
>>> x[1]['grades']
array([6.,  7.])
>>> type(x[1])
<class 'numpy.void'>
>>> type(x[1]['grades'])
<class 'numpy.ndarray'>

指定和构造数据类型#

每当 NumPy 函数或方法中需要数据类型时,都可以提供 dtype 对象或可以转换为 dtype 对象的内容.这种转换由 dtype 构造函数完成:

dtype (dtype[, align, copy])

创建一个数据类型对象.

下面描述了可转换为数据类型对象的内容:

dtype 对象

按原样使用.

None

默认数据类型 float64 .

数组标量类型

24 个内置 array scalar type objects 都转换为关联的数据类型对象. 这对其子类也适用.

请注意,并非所有数据类型信息都可以用类型对象提供:例如, flexible 数据类型的默认 itemsize 为 0,并且需要显式给定的 size 才能有用.

示例

>>> import numpy as np
>>> dt = np.dtype(np.int32)      # 32-bit integer
>>> dt = np.dtype(np.complex128) # 128-bit complex floating-point number
通用类型

通用分层类型对象根据关联转换为相应的类型对象:

自 1.19 版本弃用: 不推荐使用这种通用标量类型的转换. 这是因为在诸如 arr.astype(dtype=np.floating) 之类的上下文中,它可能是意想不到的,它将 float32 数组强制转换为 float64 数组,即使 float32np.floating 的子类型.

内置 Python 类型

当用于生成 dtype 对象时,以下几种 Python 类型等价于相应的数组标量:

Python 类型

NumPy 类型

int

int_

bool

bool_

float

float64

complex

complex128

bytes

bytes_

str

str_

memoryview

void

(所有其他类型)

object_

请注意, str_ 对应于 UCS4 编码的 Unicode 字符串.

示例

>>> import numpy as np
>>> dt = np.dtype(float)   # Python-compatible floating-point number
>>> dt = np.dtype(int)     # Python-compatible integer
>>> dt = np.dtype(object)  # Python object

备注

为方便起见,所有其他类型都映射到 object_ .代码应该预期这些类型将来可能会映射到特定的(新的) dtype.

具有 .dtype 的类型

任何具有 dtype 属性的类型对象:该属性将被访问并直接使用.该属性必须返回可转换为 dtype 对象的内容.

可以转换几种字符串. 识别的字符串可以前缀 '>' ( big-endian ), '<' ( little-endian ) 或 '=' (硬件原生,默认值) 来指定字节顺序.

单字符字符串

每个内置数据类型都有一个字符代码(更新后的 Numeric 类型代码),用于唯一标识它.

示例

>>> import numpy as np
>>> dt = np.dtype('b')  # byte, native byte order
>>> dt = np.dtype('>H') # big-endian unsigned short
>>> dt = np.dtype('<f') # little-endian single-precision float
>>> dt = np.dtype('d')  # double-precision floating-point number
数组协议类型字符串(参见 数组接口协议 )

第一个字符指定数据的种类,其余字符指定每个项目的大小(以字节为单位),但 Unicode 除外,在 Unicode 中,它被解释为字符数.项目大小必须与现有类型相对应,否则将引发错误.支持的类型如下

'?'

布尔值

'b'

(有符号)字节

'B'

无符号字节

'i'

(有符号)整数

'u'

无符号整数

'f'

浮点数

'c'

复数浮点数

'm'

timedelta

'M'

datetime

'O'

(Python) 对象

'S' , 'a'

以零结尾的字节 (不推荐)

'U'

Unicode 字符串

'V'

原始数据( void )

示例

>>> import numpy as np
>>> dt = np.dtype('i4')   # 32-bit signed integer
>>> dt = np.dtype('f8')   # 64-bit floating-point number
>>> dt = np.dtype('c16')  # 128-bit complex floating-point number
>>> dt = np.dtype('S25')  # 25-length zero-terminated bytes
>>> dt = np.dtype('U25')  # 25-character string

关于字符串类型的说明

为了与最初编写为支持 Python 2 的现有代码向后兼容, Sa 类型字符串是以零结尾的字节.对于 unicode 字符串,请使用 U , numpy.str_ .对于不需要零结尾的有符号字节,可以使用 bi1 .

带有逗号分隔字段的字符串

用于指定结构化数据类型格式的简写符号是由基本格式组成的,以逗号分隔的字符串.

在这种上下文中,基本格式是一个可选的形状说明符,后跟一个数组协议类型字符串.如果形状具有多个维度,则形状说明符上需要括号.NumPy 允许修改格式,即任何可以唯一标识类型的字符串,都可以用于指定字段中的数据类型.生成的数据类型字段被命名为 'f0' , 'f1' ,…, 'f<N-1>' ,其中 N (>1) 是字符串中以逗号分隔的基本格式的数量.如果提供了可选的形状说明符,则相应字段的数据类型描述一个子数组.

示例

  • 名为 f0 的字段,包含一个 32 位整数

  • 名为 f1 的字段,包含一个 2 x 3 的子数组,元素为 64 位浮点数

  • 名为 f2 的字段,包含一个 32 位浮点数

    >>> import numpy as np
    >>> dt = np.dtype("i4, (2,3)f8, f4")
    
  • 名为 f0 的字段,包含一个 3 字符的字符串

  • 名为 f1 的字段,包含一个形状为 (3,) 的子数组,元素为 64 位无符号整数

  • 名为 f2 的字段,包含一个 3 x 4 的子数组,元素为 10 字符的字符串

    >>> import numpy as np
    >>> dt = np.dtype("S3, 3u8, (3,4)S10")
    
类型字符串

NumPy dtype的任意字符串名称,例如:

示例

>>> import numpy as np
>>> dt = np.dtype('uint32')   # 32-bit unsigned integer
>>> dt = np.dtype('float64')  # 64-bit floating-point number
(flexible_dtype, itemsize)

第一个参数必须是可以转换为大小为零的柔性数据类型对象的对象,第二个参数是提供所需itemsize的整数.

示例

>>> import numpy as np
>>> dt = np.dtype((np.void, 10))  # 10-byte wide data block
>>> dt = np.dtype(('U', 10))   # 10-character unicode string
(fixed_dtype, shape)

第一个参数是可以转换为固定大小数据类型对象的任何对象.第二个参数是此类型的所需形状.如果shape参数为1,则用于数据类型对象等同于固定dtype.自从NumPy 1.17起,此行为已被弃用,并且将来会引发错误.如果shape是元组,则新的dtype定义给定形状的子数组.

示例

>>> import numpy as np
>>> dt = np.dtype((np.int32, (2,2)))          # 2 x 2 integer sub-array
>>> dt = np.dtype(('i4, (2,3)f8, f4', (2,3))) # 2 x 3 structured sub-array
[(field_name, field_dtype, field_shape), ...]

obj应该是字段列表,其中每个字段都由长度为2或3的元组描述.(等效于 __array_interface__ 属性中的 descr 项.)

第一个元素field_name是字段名称(如果这是 '' ,则会分配一个标准字段名称 'f#' ).该字段名称也可以是字符串的2元组,其中第一个字符串是字段的“标题”(可以是任何字符串或Unicode字符串)或元数据(可以是任何对象),第二个字符串是“名称”,它必须是有效的Python标识符.

第二个元素field_dtype可以是任何可以解释为数据类型的事物.

如果此字段表示第二个元素中数据类型的数组,则可选的第三个元素field_shape包含形状.请注意,第三个参数等于1的3元组等效于2元组.

dtype 构造函数中此样式不接受align,因为它假定所有内存都由数组接口描述负责.

示例

具有字段 big (大端 32 位整数) 和 little (小端 32 位整数) 的数据类型:

>>> import numpy as np
>>> dt = np.dtype([('big', '>i4'), ('little', '<i4')])

具有字段 R , G , B , A ,每个字段都是一个无符号的 8 位整数的数据类型:

>>> dt = np.dtype([('R','u1'), ('G','u1'), ('B','u1'), ('A','u1')])
{'names': ..., 'formats': ..., 'offsets': ..., 'titles': ..., 'itemsize': ...}

此样式有两个必需键和三个可选键. names和formats键是必需的. 它们各自的值是具有字段名称和字段格式的等长列表. 字段名称必须是字符串,并且字段格式可以是 dtype 构造函数接受的任何对象.

当提供可选键offsets和titles时,它们的值必须分别是与names和formats列表长度相同的列表. offsets值是每个字段的字节偏移量列表(限制为 ctypes.c_int ),而titles值是每个字段的标题列表 (如果不需要该字段的标题,则可以使用 None ). 标题可以是任何对象,但是当一个 str 对象时,将向字段字典添加另一个条目,该条目以标题为键,并引用同一个字段元组,该元组将包含标题作为附加元组成员.

itemsize键允许设置dtype的总大小,并且必须是一个足够大的整数,以便所有字段都在dtype内.如果正在构造的dtype已对齐,则itemsize还必须可被结构对齐方式整除.总的dtype itemsize限制为“ ctypes.c_int”.

示例

数据类型,包含字段 r , g , b , a ,每个字段都是 8 位无符号整数:

>>> import numpy as np
>>> dt = np.dtype({'names': ['r','g','b','a'],
...                'formats': [np.uint8, np.uint8, np.uint8, np.uint8]})

数据类型,包含字段 rb (具有给定的标题),均为 8 位无符号整数,第一个字段位于从字段开始的字节位置 0,第二个字段位于位置 2:

>>> dt = np.dtype({'names': ['r','b'], 'formats': ['u1', 'u1'],
...                'offsets': [0, 2],
...                'titles': ['Red pixel', 'Blue pixel']})
{'field1': ..., 'field2': ..., ...}

不鼓励使用此方法,因为它与其他基于字典的构造方法模棱两可.如果你有一个名为 ‘names’ 的字段和一个名为 ‘formats’ 的字段,则会发生冲突.

这种样式允许传入数据类型对象的 fields 属性.

obj 应该包含字符串或 unicode 键,它们引用 (data-type, offset)(data-type, offset, title) 元组.

示例

数据类型,包含字段 col1 (字节位置 0 处的 10 字符字符串), col2 (字节位置 10 处的 32 位浮点数) 和 col3 (字节位置 14 处的整数):

>>> import numpy as np
>>> dt = np.dtype({'col1': ('U10', 0), 'col2': (np.float32, 10),
...                'col3': (int, 14)})
(base_dtype, new_dtype)

在 NumPy 1.7 及更高版本中,此形式允许将 base_dtype 解释为结构化 dtype.使用此 dtype 创建的数组将具有底层 dtype base_dtype ,但将具有从 new_dtype 获取的字段和标志.这对于创建自定义结构化 dtype 非常有用,如 record arrays 中所示.

这种形式也使得能够指定具有重叠字段的 struct dtypes,其功能类似于 C 中的“union”类型.但是,不鼓励使用此用法,并且首选 union 机制.

两个参数都必须可转换为具有相同总大小的数据类型对象.

示例

32 位整数,其前两个字节通过字段 real 解释为整数,后两个字节通过字段 imag 解释.

>>> import numpy as np
>>> dt = np.dtype((np.int32,{'real':(np.int16, 0),'imag':(np.int16, 2)}))

32 位整数,被解释为包含一个形状为 (4,) 的子数组,该子数组包含 8 位整数:

>>> dt = np.dtype((np.int32, (np.int8, 4)))

32 位整数,包含字段 r , g , b , a ,这些字段将整数中的 4 个字节解释为四个无符号整数:

>>> dt = np.dtype(('i4', [('r','u1'),('g','u1'),('b','u1'),('a','u1')]))

检查数据类型#

在检查特定的数据类型时,使用 == 比较.

示例

>>> import numpy as np
>>> a = np.array([1, 2], dtype=np.float32)
>>> a.dtype == np.float32
True

与 Python 类型相反,不应使用使用 is 的比较.

首先,NumPy 将数据类型规范(可以传递给 dtype 构造函数的所有内容)视为等同于数据类型对象本身. 这种等价只能通过 == 来处理,而不能通过 is 来处理.

示例

dtype 对象等于所有等效于它的数据类型规范.

>>> import numpy as np
>>> a = np.array([1, 2], dtype=float)
>>> a.dtype == np.dtype(np.float64)
True
>>> a.dtype == np.float64
True
>>> a.dtype == float
True
>>> a.dtype == "float64"
True
>>> a.dtype == "d"
True

其次,不能保证数据类型对象是单例.

示例

不要使用 is ,因为数据类型对象可能是也可能不是单例.

>>> import numpy as np
>>> np.dtype(float) is np.dtype(float)
True
>>> np.dtype([('a', float)]) is np.dtype([('a', float)])
False

dtype#

NumPy 数据类型描述是 dtype 类的实例.

属性#

数据的类型由以下 dtype 属性描述:

dtype.type 

dtype.kind 

一个字符代码('biufcmMOSTUV' 之一),用于标识数据的一般类型.

dtype.char 

每个 21 种不同的内置类型的唯一字符代码.

dtype.num 

每种 21 种不同的内置类型的唯一编号.

dtype.str 

此数据类型对象的数组协议类型字符串.

数据的大小依次通过以下属性描述:

dtype.name 

此数据类型的位宽名称.

dtype.itemsize 

此数据类型对象元素的尺寸.

此数据的字节序:

dtype.byteorder 

一个字符,指示此数据类型对象的字节顺序.

关于 structured data type 中子数据类型的信息:

dtype.fields 

为此数据类型定义的命名字段的字典,或者 None .

dtype.names 

字段名称的有序列表,如果没有字段则为 None .

对于描述子数组的数据类型:

dtype.subdtype 

如果此 dtype 描述一个子数组,则为元组 (item_dtype, shape) ,否则为 None.

dtype.shape 

如果此数据类型描述子数组,则为子数组的形状元组,否则为 () .

提供附加信息的属性:

dtype.hasobject 

布尔值,指示此 dtype 是否在任何字段或子 dtype 中包含任何引用计数对象.

dtype.flags 

描述如何解释此数据类型的位标志.

dtype.isbuiltin 

整数,指示此 dtype 与内置 dtype 的关系.

dtype.isnative 

布尔值,指示此 dtype 的字节顺序是否为平台的本机字节顺序.

dtype.descr 

数据类型的 __ array_interface__ 描述.

dtype.alignment 

根据编译器,此数据类型所需的对齐方式(字节).

dtype.base 

返回子数组的基本元素的 dtype,无论其维度或形状如何.

用户附加的元数据:

dtype.metadata 

None 或元数据的只读字典 (mappingproxy).

方法#

数据类型具有以下更改字节顺序的方法:

dtype.newbyteorder ([new_order])

返回具有不同字节顺序的新 dtype.

以下方法实现了 pickle 协议:

dtype.__reduce__ 

pickle 的辅助方法.

dtype.__setstate__ 

用于 typing 的实用工具方法:

dtype.__class_getitem__ (item, /)

返回 dtype 类型的参数化包装器.

比较操作:

dtype.__ge__ (value, /)

返回 self>=value.

dtype.__gt__ (value, /)

返回 self>value.

dtype.__le__ (value, /)

返回 self<=value.

dtype.__lt__ (value, /)

返回 self<value.