数据类型对象 (dtype)#

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

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

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

  3. 数据的字节序(小端大端

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

    1. 结构的“字段”的名称是什么,可以通过它们进行 访问

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

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

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

为了描述标量数据的类型,NumPy 中有几种用于各种精度整数、浮点数等的 内置标量类型。从数组中提取的项(例如,通过索引)将是一个 Python 对象,其类型与数组的数据类型关联的标量类型。

请注意,标量类型不是 dtype 对象,即使在 NumPy 中需要数据类型规范时,它们可以替代 dtype 对象。

结构化数据类型是通过创建其字段包含其他数据类型的数据类型来形成的。每个字段都有一个名称,可以通过该名称进行 访问。父数据类型的大小应足以包含所有字段;父类型几乎总是基于 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,)))

此数据类型的数组项包装在 数组标量 类型中,该类型也具有两个字段

>>> 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 个内置 数组标量类型对象 都转换为关联的数据类型对象。这对于它们的子类也是如此。

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

示例

>>> 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 类型

几个 Python 类型在用于生成 dtype 对象时等效于相应的数组标量

请注意,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 对象的内容。

可以转换几种字符串。识别的字符串前面可以加上 '>'大端序)、'<'小端序)或 '='(硬件原生,默认值),以指定字节序。

单字符字符串

每个内置数据类型都有一个字符代码(更新后的 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 类型的例外是它被解释为字符数。项目大小必须与现有类型相对应,否则将引发错误。支持的类型包括:

'?'

布尔值

'b'

(带符号)字节

'B'

无符号字节

'i'

(带符号)整数

'u'

无符号整数

'f'

浮点数

'c'

复数浮点数

'm'

时间差

'M'

日期时间

'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 字符串,请使用 Unumpy.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)

第一个参数是任何可以转换为固定大小数据类型对象的任何对象。第二个参数是此类型的所需形状。如果形状参数为 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#')。字段名称也可以是两个字符串的元组,其中第一个字符串是“标题”(可以是任何字符串或 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')])

具有字段 RGBA 的数据类型,每个字段都是一个 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)。*titles* 可以是任何对象,但是当 str 对象时,它会在字段字典中添加另一个条目,该条目以标题为键,并引用包含标题作为附加元组成员的相同字段元组。

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

示例

具有字段 rgba 的数据类型,每个字段都是一个 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非常有用,如记录数组中所做的那样。

此形式还可以指定具有重叠字段的结构化dtype,其功能类似于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位整数,包含字段rgba,这些字段将整数中的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

一个字符代码('biufcmMOSUV'之一),标识数据的通用类型。

dtype.char

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

dtype.num

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

dtype.str

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

数据的大小依次由以下内容描述

dtype.name

此数据类型的位宽名称。

dtype.itemsize

此数据类型对象的大小。

此数据的字节序

dtype.byteorder

表示此数据类型对象的字节序的字符。

关于结构化数据类型中子数据类型的信息

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__

类型的实用程序方法

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。