数据类型对象 (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) 等上下文中,这种转换可能出乎意料,即使 float32np.floating 的子类型,也会将 float32 数组转换为 float64 数组。

内置 Python 类型

一些 Python 类型在生成 dtype 对象时等同于相应的数组标量:

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 对象的内容。

几种字符串可以被转换。识别的字符串可以根据需要加上 '>'大端序)、'<'小端序)或 '='(硬件原生,默认)来指定字节顺序。

单字符字符串

每种内置数据类型都有一个字符代码(更新后的 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 除外,其解释为字符数,并且 b1 表示布尔值。项大小必须对应于现有类型,否则将引发错误。支持的种类是:

'?''b1'

布尔值

'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,包含一个 2x3 的 64 位浮点数子数组

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

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

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

  • 字段命名为 f2,包含一个形状为 3x4 的 10 个字符的 Unicode 字符串子数组

    >>> 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)

第一个参数必须是一个可转换为零大小的灵活数据类型对象,第二个参数是一个提供所需项大小的整数。

示例

>>> 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 中的“联合”类型。然而,不推荐使用此用法,并且首选联合机制。

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

示例

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

一个字符代码('biufcmMOSTUV' 中的一个),用于识别数据的通用种类。

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.__class_getitem__(item, /)

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

比较操作

dtype.__ge__(value, /)

返回 self>=value。

dtype.__gt__(value, /)

返回 self>value。

dtype.__le__(value, /)

返回 self<=value。

dtype.__lt__(value, /)

返回 self<value。