说明
NumPy 教程 持续更新中,提供建议、纠错、催更等加作者微信: gr99123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
Python 仅定义特定数据类的一种类型(只有一种整数类型,一种浮点类型等),在不需要关心计算机中数据表示方式的所有应用程序中很方便,但是,对于科学计算,通常需要更多的控制。
标量(Scalar)就是非向量,一个单一的值,numpy 尝试将其向量解析为单个数字(即 python 标量),当向量的长度不是1时将失败。由于传统的 Python 类型( 如数字 float 和 integer)过于原始,因此需要更复杂的数据类型。
NumPy 通常以 array 标量(array scalars,带有关联数据类型的标量)的形式返回数组的元素。array 标量不同于 Python 标量,但它们在大多数情况下可以互换使用(主要的例外是对于Python v2.x之前的版本,其中 integer 标量不能作为列表和元组的索引)。也有一些例外,例如当代码需要非常特定的标量属性时,或者当它专门检查某个值是否是 Python 标量时。通常,通过使用相应的 Python 类型函数(例如 int、float、complex、str、unicode)将数组标量显式转换为 Python标量,问题很容易得到解决。
使用 array 标量的主要优点是保留了数组类型(Python 可能没有匹配的标量类型,例如 int16)。因此,使用 array 标量可以确保数组和标量之间的行为相同而不用管值是否在数组中。NumPy 标量也有许多与数组相同的方法。
NumPy 的标量它还声明了标量类型(数据类型层次结构)以及标量的几个属性。
a = np.array([1,2,3])
float(a)
# TypeError: only size-1 arrays can be converted to Python scalars
b = np.array([1])
float(b)
# 1.0
Array 标量与 ndarray 具有相同的属性和方法(但是,Array 标量是不可变的,因此没有一个数组标量属性是可设置的),这样一来,就可以部分地将数组的项与数组放在相同的位置,从而平滑混合标量和数组操作时产生的粗糙边缘。
数组标量位于数据类型的层次结构中(请参见下图)。 可以使用层次结构检测它们:例如,如果 val 是一个数组标量对象,则isinstance(val, np.generic)
将返回 True。 或者,可以使用数据类型层次结构的其他成员来确定存在哪种数组标量。 因此,例如,如果 val 是复数值类型,则isinstance(val, np.complexfloating)
将返回 True,而如果 val 是灵活的 itemsize 数组类型之一 (str_, bytes_, void)。
在 NumPy 中,有 24 种新的基本Python类型来描述不同类型的标量。 这些类型描述符主要基于编写 CPython 的 C 语言中可用的类型,以及与 Python 类型兼容的其他几种类型。
图:表示数组数据类型的类型对象的层次结构。未显示的是两个整数类型 intp 和uintp,它们只指向保存平台指针的整数类型,所有数字类型也可以使用位宽名称获得
内置标量类型如下所示。类似 C 的名称与字符代码相关联,字符代码显示在它们的描述中。但是,不鼓励使用字符代码。一些标量类型本质上等同于基本的 Python 类型,因此继承自它们以及泛型数组标量类型:
Array 标量类型 | 相关 Python 类型 | 继承? |
---|---|---|
int_ | int | Python 2 only |
float_ | float | yes |
complex_ | complex | yes |
bytes_ | bytes | yes |
str_ | str | yes |
bool_ | bool | no |
datetime64 | datetime.datetime | no |
timedelta64 | datetime.timedelta | no |
其中:
bool_
数据类型与 Python bool 非常相似,但并不从中继承,因为 Python 的 bool 不允许自己从中继承,而且在 C 级上,实际 bool 数据的大小与 Python 布尔标量不同。numpy.generic 是 numpy 标量类型的基类,大多数(所有?)numpy 派生标量的类型出自它。为了保持一致性,公开了与 ndarray 相同的API,尽管许多后续属性要么是 “get only”,要么是完全不相关的。强烈建议用户从该类派生自定义标量类型。
类 generic 的存在仅仅是为了从 ndarray 类派生 numpy 标量,并且拥有 ndarray 类的所有属性(虚拟属性,尽管尚未实现),以便提供统一的API。
numpy.number 是所有数值标量类型的抽象基类。下表中,平台?
表示该类型可能并非在所有平台上都可用。
类型 | 备注 | 字符代码 |
---|---|---|
np.bool_ | 兼容:Python bool | '?' |
np.bool8 | 8位 |
类型 | 备注 | 字符代码 |
---|---|---|
np.byte | 兼容:C char | 'b' |
np.short | 兼容:C短 | 'h' |
np.intc | 兼容:C int | 'i' |
np.int_ | 兼容:Python int | 'l' |
np.longlong | 兼容:C长 | 'q' |
np.intp | 大到足以适合指针 | 'p' |
np.int8 | 8位 | |
np.int16 | 16位 | |
np.int32 | 32位 | |
np.int64 | 64位 |
类型 | 备注 | 字符代码 |
---|---|---|
np.ubyte | compatible:C unsigned char | 'B' |
np.ushort | 兼容:C unsigned short | 'H' |
np.uintc | compatible:C unsigned int | 'I' |
np.uint | 兼容:Python int | 'L' |
np.ulonglong | 兼容:C长 | 'Q' |
np.uintp | 大到足以适合指针 | 'P' |
np.uint8 | 8位 | |
np.uint16 | 16位 | |
np.uint32 | 32位 | |
np.uint64 | 64位 |
类型 | 备注 | 字符代码 |
---|---|---|
np.half | 'e' | |
np.single | 兼容:C浮动 | 'f' |
np.double | 兼容:C双 | |
np.float_ | 兼容:Python float | 'd' |
np.longfloat | 兼容:C长浮 | 'g' |
np.float16 | 16位 | |
np.float32 | 32位 | |
np.float64 | 64位 | |
np.float96 | 96位,平台? | |
np.float128 | 128位,平台? |
类型 | 备注 | 字符代码 |
---|---|---|
np.csingle | 'F' | |
np.complex_ | 兼容:Python复杂 | 'D' |
np.clongfloat | 'G' | |
np.complex64 | 两个32位浮点数 | |
np.complex128 | 两个64位浮点数 | |
np.complex192 | 两个96位浮动平台? | |
np.complex256 | 两个128位浮点数,平台? |
类型 | 备注 | 字符代码 |
---|---|---|
np.object_ | 任何Python对象 | 'O' |
注意:
实际存储在对象数组中的数据( 即 具有dtype的数组object_)是对 Python 对象的引用,而不是对象本身。因此,对象数组的行为更像普通的 Python lists,因为它们的内容不必是相同的 Python 类型。
对象类型也是特殊的,因为包含 object_ 项的数组 不会 object_ 在项访问时返回对象,而是返回数组项引用的实际对象。
以下数据类型是灵活的:它们没有预定义的大小,并且它们描述的数据在不同的数组中可以具有不同的长度。(在字符代码中#是一个整数,表示数据类型包含多少个元素。)
类型 | 备注 | 字符代码 |
---|---|---|
np.bytes_ | 兼容:Python字节 | 'S#' |
np.unicode_ | 兼容:Python unicode / str | 'U#' |
np.void | 'V#' |
以下别名源于 python 2,建议不要在新代码中使用它们:
numpy.string_
alias of numpy.bytes_
numpy.unicode_
alias of numpy.str_
如果在数字代码中使用了旧的类型代码字符(不推荐), 则需要将其中一些更改为新字符。 特别是,所需的更改是 c -> S1, b -> B, 1 -> b, s -> h, w -> H 和 u -> I。 这些更改使类型字符约定与其他 Python 更加一致 诸如 struct 模块之类的模块。
类 generic 的存在仅仅是为了从 ndarray 类派生 numpy 标量,并且拥有 ndarray 类的所有属性(虚拟属性,尽管尚未实现),以便提供统一的API。
数组标量对象的数组优先级为 NPY_SCALAR_PRIORITY (-1,000,000.0)。它们还没有 ctypes 属性。否则,它们与数组共享相同的属性:
方法 | 描述 |
---|---|
generic.flags | 标志的整数值 |
generic.shape | 数组维度的元组 |
generic.strides | 每个维度中的字节元组步骤 |
generic.ndim | 数组维数 |
generic.data | 指向数据开始的指针 |
generic.size | gentype中的元素数量 |
generic.itemsize | 一个元素的长度,以字节为单位 |
generic.base | 基础对象 |
generic.dtype | 获取数组数据描述符 |
generic.real | 标量的真实部分 |
generic.imag | 标量的虚部 |
generic.flat | 标量的一维视图 |
generic.T | 转置 |
generic.__array_interface__ |
数组协议:Python 端 |
generic.__array_struct__ |
数组协议:struct |
generic.__array_priority__ |
数组优先级。 |
generic.__array_wrap__ |
sc.__array_wrap__(obj) 从数组返回标量 |
数组标量可以像 0 维数组一样索引,如果 x 是数组标量:
数组标量具有与数组完全相同的方法。这些方法的默认行为是在内部将标量转换为等效的0维数组并调用相应的数组方法。 此外,数组标量的数学运算被定义,使得在相同的硬件标志被设置, 并用于解释结果作为通函数(ufunc), 使得用于ufuncs错误状态也延续到上数组标量的数学。
以上规则的例外情况如下:
方法 | 描述 |
---|---|
generic.__array__ |
sc.__array__(dtype) 从带有指定dtype的标量返回0-dim数组 |
generic.__array_wrap__ |
sc.__array_wrap__(obj) 从数组返回标量 |
generic.squeeze | 未实现((虚拟属性)与对应数组属性相同的标量方法, 下同 |
generic.byteswap | 未实现(虚拟属性) |
generic.__reduce__ |
Helper for pickle. |
generic.__setstate__ |
|
generic.setflags | 未实现(虚拟属性) |
有两种方法可以有效地定义新的数组标量类型(除了从内置标量类型组合结构化类型dtypes):一种方法是简单地子类化 ndarray 并覆盖感兴趣的方法。 这将在一定程度上起作用,但内部某些行为由数组的数据类型修复。要完全自定义数组的数据类型, 您需要定义新的数据类型,并使用 NumPy 进行注册。 这些新类型只能使用 NumPy C-API 在 C 中定义。
更新时间:2021-01-07 12:29:53 标签:numpy 标量