数组 API#

一流智力的标志是能够同时持有两种
对立的想法,并且仍然保留
运作能力.
— F. Scott Fitzgerald
对于一个成功的技术,现实必须优先于公共
关系,因为自然是不可欺骗的.
— Richard P. Feynman

数组结构和数据访问#

这些宏访问 PyArrayObject 结构成员,并在 ndarraytypes.h 中定义.输入参数 arr 可以是任何可直接解释为 PyObject*PyArrayObject* ( PyArray_Type 及其子类型的任何实例).

int PyArray_NDIM(PyArrayObject *arr)#

数组中的维数.

int PyArray_FLAGS(PyArrayObject *arr)#

返回表示 array-flags 的整数.

int PyArray_TYPE(PyArrayObject *arr)#

返回此数组元素的(内置)类型编号.

int PyArray_Pack(const PyArray_Descr *descr, void *item, const PyObject *value)#

在 2.0 版本加入.

将 dtype descr 的内存位置 item 设置为 value .

该函数等效于使用 Python 赋值设置单个数组元素.成功时返回 0,失败时返回 -1 并设置错误.

备注

如果设置了 descr 具有 NPY_NEEDS_INIT 标志,则数据必须有效或将内存清零.

int PyArray_SETITEM(PyArrayObject *arr, void *itemptr, PyObject *obj)#

转换 obj 并将其放置在 ndarray arr 中的 itemptr 指向的位置.如果发生错误,则返回 -1,成功则返回 0.

备注

通常,在处理任意 Python 对象时,首选使用 PyArray_Pack .例如,Setitem 无法处理不同 dtype 之间的任意转换.

void PyArray_ENABLEFLAGS(PyArrayObject *arr, int flags)#

启用指定的数组标志.此函数不做任何验证,并假定您知道自己在做什么.

void PyArray_CLEARFLAGS(PyArrayObject *arr, int flags)#

清除指定的数组标志.此函数不做任何验证,并假定您知道自己在做什么.

void *PyArray_DATA(PyArrayObject *arr)#
char *PyArray_BYTES(PyArrayObject *arr)#

这两个宏类似,并获取数组数据缓冲区的指针.第一个宏可以(并且应该)分配给特定指针,而第二个宏用于通用处理.如果您不保证连续和/或对齐的数组,请务必了解如何访问数组中的数据,以避免内存和/或对齐问题.

npy_intp *PyArray_DIMS(PyArrayObject *arr)#

返回指向数组维度/形状的指针.元素的数量与数组的维度数匹配.对于 0 维数组,可以返回 NULL .

npy_intp *PyArray_SHAPE(PyArrayObject *arr)#

PyArray_DIMS 同义,命名是为了与 Python 中的 shape 用法保持一致.

npy_intp *PyArray_STRIDES(PyArrayObject *arr)#

返回指向数组步长的指针.元素的数量与数组的维度数匹配.

npy_intp PyArray_DIM(PyArrayObject *arr, int n)#

返回第 n \(^{\textrm{th}}\) 维度的形状.

npy_intp PyArray_STRIDE(PyArrayObject *arr, int n)#

返回第 n \(^{\textrm{th}}\) 维度的步长.

npy_intp PyArray_ITEMSIZE(PyArrayObject *arr)#

返回此数组的元素的 itemsize.

请注意,在 1.7 版本中已弃用的旧 API 中,此函数的返回类型为 int .

npy_intp PyArray_SIZE(PyArrayObject *arr)#

返回数组的总大小(以元素数为单位).

npy_intp PyArray_Size(PyObject *obj)#

如果 obj 不是 ndarray 的子类,则返回 0.否则,返回数组中的元素总数. PyArray_SIZE (obj) 的更安全版本.

npy_intp PyArray_NBYTES(PyArrayObject *arr)#

返回数组消耗的总字节数.

PyObject *PyArray_BASE(PyArrayObject *arr)#

这将返回数组的基础对象.在大多数情况下,这意味着拥有数组指向的内存的对象.

如果您正在使用 C API 构建数组,并指定您自己的内存,则应使用函数 PyArray_SetBaseObject 将 base 设置为拥有内存的对象.

如果设置了 NPY_ARRAY_WRITEBACKIFCOPY 标志,它具有不同的含义,即 base 是在复制解析后当前数组将复制到的数组.这种对 base 属性的两种功能进行重载可能会在 NumPy 的未来版本中发生变化.

PyArray_Descr *PyArray_DESCR(PyArrayObject *arr)#

返回对数组的 dtype 属性的借用引用.

PyArray_Descr *PyArray_DTYPE(PyArrayObject *arr)#

与 PyArray_DESCR 同义,命名是为了与 Python 中的 ‘dtype’ 用法保持一致.

PyObject *PyArray_GETITEM(PyArrayObject *arr, void *itemptr)#

从 itemptr 指向的位置处的ndarray,arr,获取一个内置类型的 Python 对象.失败时返回 NULL .

numpy.ndarray.item 与 PyArray_GETITEM 相同.

int PyArray_FinalizeFunc(PyArrayObject *arr, PyObject *obj)#

PyCapsule __array_finalize__ 指向的函数.第一个参数是新创建的子类型.第二个参数(如果不是 NULL)是 “父” 数组(如果数组是使用切片或一些其他操作创建的,其中存在一个可明显区分的父数组).此例程可以执行任何它想执行的操作.如果出错,它应该返回 -1,否则返回 0.

数据访问#

这些函数和宏提供从 C 轻松访问 ndarray 元素的方法.这些适用于所有数组.但是,如果数组不是机器字节顺序,未对齐或不可写,则在访问数组中的数据时可能需要小心.换句话说,请务必尊重标志的状态,除非您知道自己在做什么,或者之前使用 PyArray_FromAny 保证了可写,对齐且为机器字节顺序的数组.如果您希望处理所有类型的数组,则每种类型的 copyswap 函数对于处理行为不端的数组非常有用.某些平台(例如 Solaris)不喜欢未对齐的数据,如果取消引用未对齐的指针,则会崩溃.其他平台(例如 x86 Linux)在处理未对齐的数据时只会更慢.

void *PyArray_GetPtr(PyArrayObject *aobj, npy_intp *ind)#

返回指向 ndarray aobj 的数据的指针,该指针位于由 c 数组 ind 给出的 N 维索引处(该 c 数组的大小必须至少为 aobj ->nd).您可能希望将返回的指针强制转换为 ndarray 的数据类型.

void *PyArray_GETPTR1(PyArrayObject *obj, npy_intp i)#
void *PyArray_GETPTR2(PyArrayObject *obj, npy_intp i, npy_intp j)#
void *PyArray_GETPTR3(PyArrayObject *obj, npy_intp i, npy_intp j, npy_intp k)#
void *PyArray_GETPTR4(PyArrayObject *obj, npy_intp i, npy_intp j, npy_intp k, npy_intp l)#

快速,内联访问 ndarray obj 中给定坐标处的元素,该 obj 必须分别具有 1,2,3 或 4 个维度(这未经过检查).相应的 i,j,k 和 l 坐标可以是任何整数,但将被解释为 npy_intp .您可能希望将返回的指针强制转换为 ndarray 的数据类型.

创建数组#

从头开始#

PyObject *PyArray_NewFromDescr(PyTypeObject *subtype, PyArray_Descr *descr, int nd, npy_intp const *dims, npy_intp const *strides, void *data, int flags, PyObject *obj)#

此函数会窃取对 descr 的引用.获取它的最简单方法是使用 PyArray_DescrFromType .

这是主要的数组创建函数.大多数新数组都是使用此灵活函数创建的.

返回的对象是 Python 类型 subtype 的对象,它必须是 PyArray_Type 的子类型.数组具有 nd 维,由 dims 描述.新数组的数据类型描述符是 descr.

如果 subtype 是数组子类而不是基类 &PyArray_Type ,则 obj 是传递给子类的 __array_finalize__ 方法的对象.

如果 data 是 NULL ,则将分配新的未初始化内存,并且 flags 可以为非零,以指示 Fortran 样式的连续数组.使用 PyArray_FILLWBYTE 初始化内存.

如果 data 不是 NULL ,则假定它指向用于数组的内存,并且 flags 参数用作数组的新标志(除了 NPY_ARRAY_OWNDATA 的状态之外,将重置新数组的 NPY_ARRAY_WRITEBACKIFCOPY 标志).

此外,如果 data 为非 NULL,则还可以提供 strides.如果 strides 是 NULL ,则数组步幅被计算为 C 样式连续(默认)或 Fortran 样式连续(flags 对于 data = NULL 为非零,或者 flags & NPY_ARRAY_F_CONTIGUOUS 对于非 NULL 数据为非零).任何提供的 dims 和 strides 都会被复制到新分配的维度和步幅数组中,以用于新的数组对象.

PyArray_CheckStrides 可以帮助验证非 NULL 的步幅信息.

如果提供了 data ,则它必须在数组的生命周期内保持有效.管理此问题的一种方法是通过 PyArray_SetBaseObject

PyObject *PyArray_NewLikeArray(PyArrayObject *prototype, NPY_ORDER order, PyArray_Descr *descr, int subok)#

如果 descr 不为 NULL,则此函数会窃取对 descr 的引用.此数组创建例程允许方便地创建与现有数组的形状和内存布局匹配的新数组,可能更改布局和/或数据类型.

当 order 为 NPY_ANYORDER 时,如果 prototype 是 Fortran 数组,则结果 order 为 NPY_FORTRANORDER ,否则为 NPY_CORDER .当 order 为 NPY_KEEPORDER 时,结果 order 与 prototype 的 order 匹配,即使 prototype 的轴不是 C 或 Fortran order.

如果 descr 为 NULL,则使用 prototype 的数据类型.

如果 subok 为 1,则新创建的数组将使用 prototype 的子类型来创建新数组,否则它将创建一个基类数组.

PyObject *PyArray_New(PyTypeObject *subtype, int nd, npy_intp const *dims, int type_num, npy_intp const *strides, void *data, int itemsize, int flags, PyObject *obj)#

这与 PyArray_NewFromDescr (…) 类似,但您可以使用 type_num 和 itemsize 指定数据类型描述符,其中 type_num 对应于内置(或用户定义)类型.如果类型始终具有相同数量的字节,则忽略 itemsize.否则,itemsize 指定此数组的特定大小.

警告

如果将 data 传递给 PyArray_NewFromDescrPyArray_New ,则在删除新数组之前,不得释放此内存.如果此数据来自另一个 Python 对象,则可以通过对该对象使用 Py_INCREF 并将新数组的 base 成员设置为指向该对象来实现.如果传入 strides,则它们必须与维度,itemsize 和数组数据保持一致.

PyObject *PyArray_SimpleNew(int nd, npy_intp const *dims, int typenum)#

创建一个类型为 typenum 的新的未初始化数组,其在每个 nd 维度中的大小由整数数组 dims 给定.数组的内存是未初始化的(除非 typenum 是 NPY_OBJECT ,在这种情况下,数组中的每个元素都设置为 NULL).typenum 参数允许指定任何内置数据类型,例如 NPY_FLOATNPY_LONG .如果需要,可以使用 PyArray_FILLWBYTE (return_object, 0) 将数组的内存设置为零.此函数不能用于创建灵活类型数组(未给出 itemsize).

PyObject *PyArray_SimpleNewFromData(int nd, npy_intp const *dims, int typenum, void *data)#

在给定指针指向的数据周围创建一个新的数组包装器.数组标志将具有一个默认值,即数据区域行为良好且 C 样式连续.数组的形状由长度为 nd 的 dims c 数组给出.数组的数据类型由 typenum 指示.如果数据来自另一个引用计数的 Python 对象,则在传入指针后,应增加此对象的引用计数,并且返回的 ndarray 的 base 成员应指向拥有数据的 Python 对象.这将确保在返回的数组存在期间不释放提供的内存.

PyObject *PyArray_SimpleNewFromDescr(int nd, npy_int const *dims, PyArray_Descr *descr)#

此函数会窃取对 descr 的引用.

使用提供的数据类型描述符 descr 创建一个新数组,其形状由 nd 和 dims 确定.

void PyArray_FILLWBYTE(PyObject *obj, int val)#

用 val(评估为字节)的内容填充 obj 指向的数组 — 它必须是 ndarray(或其子类)—.此宏调用 memset,因此 obj 必须是连续的.

PyObject *PyArray_Zeros(int nd, npy_intp const *dims, PyArray_Descr *dtype, int fortran)#

构造一个新的 nd 维数组,其形状由 dims 给定,数据类型由 dtype 给定.如果 fortran 非零,则创建 Fortran 顺序的数组,否则创建 C 顺序的数组.用零填充内存(如果 dtype 对应于 NPY_OBJECT ,则填充 0 对象).

PyObject *PyArray_ZEROS(int nd, npy_intp const *dims, int type_num, int fortran)#

PyArray_Zeros 的宏形式,它接受类型编号而不是数据类型对象.

PyObject *PyArray_Empty(int nd, npy_intp const *dims, PyArray_Descr *dtype, int fortran)#

构造一个新的 nd 维数组,其形状由 dims 给定,数据类型由 dtype 给定.如果 fortran 非零,则创建 Fortran 顺序的数组,否则创建 C 顺序的数组.除非数据类型对应于 NPY_OBJECT ,否则数组未初始化,在这种情况下,数组将填充 Py_None .

PyObject *PyArray_EMPTY(int nd, npy_intp const *dims, int typenum, int fortran)#

PyArray_Empty 的宏形式,它接受类型编号 typenum,而不是数据类型对象.

PyObject *PyArray_Arange(double start, double stop, double step, int typenum)#

构造一个新的数据类型为 typenum 的一维数组,该数组的范围从 start 到 stop(不包括 stop),增量为 step.等效于 arange (start, stop, step, dtype).

PyObject *PyArray_ArangeObj(PyObject *start, PyObject *stop, PyObject *step, PyArray_Descr *descr)#

构造一个新的数据类型由 descr 确定的一维数组,该数组的范围从 startstop (不包括 stop ),增量为 step .等效于 arange( start , stop , step , typenum ).

int PyArray_SetBaseObject(PyArrayObject *arr, PyObject *obj)#

此函数会窃取对 obj 的引用,并将其设置为 arr 的 base 属性.

如果通过传入您自己的内存缓冲区作为参数来构造数组,则需要设置数组的 base 属性以确保内存缓冲区的生命周期是适当的.

返回值是 0 表示成功,-1 表示失败.

如果提供的对象是一个数组,则此函数会遍历 base 指针链,以便每个数组直接指向内存的所有者.一旦设置了 base,就不能将其更改为其他值.

从其他对象#

PyObject *PyArray_FromAny(PyObject *op, PyArray_Descr *dtype, int min_depth, int max_depth, int requirements, PyObject *context)#

这是用于从任何嵌套序列或公开数组接口的对象 op 获取数组的主要函数.参数允许指定所需的 dtype,可接受的最小 (min_depth) 和最大 (max_depth) 维度数以及数组的其他要求.此函数会窃取对 dtype 参数的引用,dtype 参数需要是一个 PyArray_Descr 结构,指示所需的数据类型(包括所需的字节顺序).dtype 参数可以为 NULL ,表示任何数据类型(和字节顺序)都是可接受的.除非 flags 中存在 NPY_ARRAY_FORCECAST ,否则如果无法从对象安全地获取数据类型,则此调用将生成错误.如果您想为 dtype 使用 NULL 并确保数组未交换,请使用 PyArray_CheckFromAny .深度参数中的任何一个值为 0 都会导致该参数被忽略.可以将以下任何数组标志添加到 requirements 参数中(例如,使用 |).如果您的代码可以处理通用的(例如,跨步的,字节交换的或未对齐的数组),则 requirements 可以为 0.此外,如果 op 还不是数组(或者没有公开数组接口),则将创建一个新数组(并使用序列协议从 op 填充).新数组将具有 NPY_ARRAY_DEFAULT 作为其 flags 成员.context 参数未使用.

NPY_ARRAY_C_CONTIGUOUS

确保返回的数组是 C 风格的连续数组

NPY_ARRAY_F_CONTIGUOUS

确保返回的数组是 Fortran 风格的连续数组.

NPY_ARRAY_ALIGNED

确保返回的数组在其数据类型的正确边界上对齐.对齐的数组的数据指针和每个 strides 因子都是数据类型描述符的对齐因子的倍数.

NPY_ARRAY_WRITEABLE

确保返回的数组可以写入.

NPY_ARRAY_ENSURECOPY

确保制作 op 的副本.如果不存在此标志,则如果可以避免,则不会复制数据.

NPY_ARRAY_ENSUREARRAY

确保结果是一个基类ndarray. 默认情况下,如果 op 是 ndarray 子类的实例,则返回该相同子类的实例. 如果设置了此标志,则将返回一个 ndarray 对象.

NPY_ARRAY_FORCECAST

强制转换为输出类型,即使它不能安全地完成. 如果没有此标志,则只有在可以安全完成数据类型转换时才会进行转换,否则会引发错误.

NPY_ARRAY_WRITEBACKIFCOPY

如果 op 已经是一个数组,但不满足要求,则会创建一个副本(该副本将满足要求). 如果存在此标志并且必须创建副本(已经是数组的对象的副本),则在返回的副本中设置相应的 NPY_ARRAY_WRITEBACKIFCOPY 标志,并且 op 设置为只读. 您必须确保调用 PyArray_ResolveWritebackIfCopy 将内容复制回 op,并且 op 数组将再次变为可写. 如果 op 从一开始就不可写,或者如果它还不是数组,则会引发错误.

Combinations of array flags 也可以添加.

PyObject *PyArray_CheckFromAny(PyObject *op, PyArray_Descr *dtype, int min_depth, int max_depth, int requirements, PyObject *context)#

PyArray_FromAny (…) 几乎相同,只是 requirements 可以包含 NPY_ARRAY_NOTSWAPPED (覆盖 dtype 中的规范)和 NPY_ARRAY_ELEMENTSTRIDES ,这表示数组应该对齐,即 strides 是元素大小的倍数.

PyObject *PyArray_FromArray(PyArrayObject *op, PyArray_Descr *newtype, int requirements)#

PyArray_FromAny 的特殊情况,用于 op 已经是数组但需要特定的 newtype (包括字节顺序)或具有某些要求的情况.

PyObject *PyArray_FromStructInterface(PyObject *op)#

从一个 Python 对象返回一个 ndarray 对象,该对象公开了 __array_struct__ 属性并遵循数组接口协议. 如果该对象不包含此属性,则返回对 Py_NotImplemented 的借用引用.

PyObject *PyArray_FromInterface(PyObject *op)#

从一个 Python 对象返回一个 ndarray 对象,该对象公开了 __array_interface__ 属性并遵循数组接口协议. 如果该对象不包含此属性,则返回对 Py_NotImplemented 的借用引用.

PyObject *PyArray_FromArrayAttr(PyObject *op, PyArray_Descr *dtype, PyObject *context)#

从一个 Python 对象返回一个 ndarray 对象,该对象公开了 __array__ 方法. __array__ 的第三方实现必须接受 dtypecopy 关键字参数. context 未使用.

PyObject *PyArray_ContiguousFromAny(PyObject *op, int typenum, int min_depth, int max_depth)#

此函数从任何嵌套序列或数组接口导出对象 op 返回一个(C 风格的)连续且表现良好的函数数组,该数组的类型由枚举的 typenum 给定,最小深度为 min_depth,最大深度为 max_depth. 相当于调用 PyArray_FromAny ,其中 requirements 设置为 NPY_ARRAY_DEFAULT ,并且 type 参数的 type_num 成员设置为 typenum.

PyObject *PyArray_ContiguousFromObject(PyObject *op, int typenum, int min_depth, int max_depth)#

此函数从任何嵌套序列或数组接口导出对象返回一个表现良好的 C 风格的连续数组. 数组可以具有的最小维数由 min_depth 给出,而最大维数由 max_depth 给出. 这相当于调用 PyArray_FromAny ,其中 requirements 为 NPY_ARRAY_DEFAULTNPY_ARRAY_ENSUREARRAY .

PyObject *PyArray_FromObject(PyObject *op, int typenum, int min_depth, int max_depth)#

从任何嵌套序列或数组接口导出对象 op 返回一个对齐的且以本机字节顺序排列的数组,该数组的类型由枚举的 typenum 给出. 数组可以具有的最小维数由 min_depth 给出,而最大维数由 max_depth 给出. 这相当于调用 PyArray_FromAny ,其中 requirements 设置为 BEHAVED.

PyObject *PyArray_EnsureArray(PyObject *op)#

此函数窃取对 op 的引用,并确保 op 是一个基类 ndarray. 它特殊处理数组标量,否则调用 PyArray_FromAny ( op , NULL, 0, 0, NPY_ARRAY_ENSUREARRAY , NULL).

PyObject *PyArray_FromString(char *string, npy_intp slen, PyArray_Descr *dtype, npy_intp num, char *sep)#

从长度为 slen 的二进制或(ASCII)文本 string 构造一个单一类型的一维 ndarray. 要创建的数组的数据类型由 dtype 给出. 如果 num 为 -1,则复制整个字符串并返回一个适当大小的数组,否则, num 是要从字符串复制的项目数. 如果 sep 为 NULL(或 “”),则将字符串解释为二进制数据的字节,否则将由 sep 分隔的子字符串转换为数据类型 dtype 的项目. 某些数据类型可能无法以文本模式读取,如果发生这种情况,将引发错误. 所有错误都返回 NULL.

PyObject *PyArray_FromFile(FILE *fp, PyArray_Descr *dtype, npy_intp num, char *sep)#

从二进制或文本文件中构造一个单一类型的,一维的 ndarray.打开的文件指针是 fp ,要创建的数组的数据类型由 dtype 给出.这必须与文件中的数据匹配.如果 num 是 -1,则读取到文件末尾并返回一个适当大小的数组;否则, num 是要读取的项数.如果 sep 为 NULL (或 “”),则以二进制模式从文件读取;否则,以文本模式从文件读取, sep 提供项分隔符.某些数组类型无法以文本模式读取,在这种情况下会引发错误.

PyObject *PyArray_FromBuffer(PyObject *buf, PyArray_Descr *dtype, npy_intp count, npy_intp offset)#

从对象 buf 构造一个单一类型的,一维的 ndarray,该对象导出(单段)缓冲区协议(或具有一个属性 __buffer__,该属性返回一个导出缓冲区协议的对象).将首先尝试可写缓冲区,然后是只读缓冲区.返回数组的 NPY_ARRAY_WRITEABLE 标志将反映哪个缓冲区成功.假设数据从对象内存位置的 offset 字节处开始.缓冲区中的数据类型将根据数据类型描述符 dtype 进行解释.如果 count 为负数,则将根据缓冲区的大小和请求的 itemsize 确定;否则, count 表示应从缓冲区转换的元素数量.

int PyArray_CopyInto(PyArrayObject *dest, PyArrayObject *src)#

从源数组 src 复制到目标数组 dest ,并在必要时执行数据类型转换.如果发生错误,则返回 -1(否则返回 0). src 的形状必须可广播到 dest 的形状.NumPy 在复制两个数组时会检查内存是否重叠.

int PyArray_CopyObject(PyArrayObject *dest, PyObject *src)#

根据数组强制转换规则,将对象 src 赋值给 NumPy 数组 dest .这基本上与 PyArray_FromAny 相同,但直接赋值给输出数组.成功时返回 0,失败时返回 -1.

PyArrayObject *PyArray_GETCONTIGUOUS(PyObject *op)#

如果 op 已经是(C 风格的)连续且行为良好的数组,则只需返回一个引用;否则,返回该数组的(连续且行为良好的)副本.参数 op 必须是 ndarray (的子类),并且不进行任何检查.

PyObject *PyArray_FROM_O(PyObject *obj)#

obj 转换为 ndarray.该参数可以是任何嵌套序列或导出数组接口的对象.这是 PyArray_FromAny 的宏观形式,对其他参数使用 NULL ,0,0,0.您的代码必须能够处理任何数据类型描述符和数据标志的任何组合才能使用此宏.

PyObject *PyArray_FROM_OF(PyObject *obj, int requirements)#

类似于 PyArray_FROM_O ,但它可以接受一个 requirements 参数,指示结果数组必须具有的属性.可以强制执行的可用 requirements 包括 NPY_ARRAY_C_CONTIGUOUS , NPY_ARRAY_F_CONTIGUOUS , NPY_ARRAY_ALIGNED , NPY_ARRAY_WRITEABLE , NPY_ARRAY_NOTSWAPPED , NPY_ARRAY_ENSURECOPY , NPY_ARRAY_WRITEBACKIFCOPY , NPY_ARRAY_FORCECASTNPY_ARRAY_ENSUREARRAY .也可以使用标志的标准组合:

PyObject *PyArray_FROM_OT(PyObject *obj, int typenum)#

类似于 PyArray_FROM_O ,但它可以接受一个 typenum 参数,指定返回数组的类型编号.

PyObject *PyArray_FROM_OTF(PyObject *obj, int typenum, int requirements)#

PyArray_FROM_OFPyArray_FROM_OT 的组合,允许同时提供 typenum 和 flags 参数.

PyObject *PyArray_FROMANY(PyObject *obj, int typenum, int min, int max, int requirements)#

类似于 PyArray_FromAny ,只不过数据类型是使用类型编号指定的. PyArray_DescrFromType (typenum) 直接传递给 PyArray_FromAny .如果 NPY_ARRAY_DEFAULT 作为 requirements 传入,则此宏还会将 NPY_ARRAY_ENSURECOPY 添加到 requirements.

PyObject *PyArray_CheckAxis(PyObject *obj, int *axis, int requirements)#

封装接受 axis= 关键字并在将 None 作为 axis 参数时正常工作的函数和方法的功能.输入数组是 obj ,而 *axis 是一个转换后的整数(因此 *axis == NPY_RAVEL_AXIS 是 None 值),并且 requirements 给出了 obj 所需的属性.输出是输入的转换版本,以便满足 requirements,并且在需要时发生了展平.在输出时, *axis 的负值被转换,并且检查新值以确保与 obj 的形状一致.

处理类型#

Python 类型的一般检查#

int PyArray_Check(PyObject *op)#

如果 op 是一个 Python 对象,且其类型是 PyArray_Type 的子类型,则求值为真.

int PyArray_CheckExact(PyObject *op)#

如果 op 是一个类型为 PyArray_Type 的 Python 对象,则求值为真.

int PyArray_HasArrayInterface(PyObject *op, PyObject *out)#

如果 op 实现了数组接口的任何部分,则 out 将包含对使用该接口新创建的 ndarray 的新引用,或者如果转换期间发生错误,则 out 将包含 NULL .否则,out 将包含对 Py_NotImplemented 的借用引用,并且不设置任何错误条件.

int PyArray_HasArrayInterfaceType(PyObject *op, PyArray_Descr *dtype, PyObject *context, PyObject *out)#

如果 op 实现了数组接口的任何部分,则 out 将包含对使用该接口新创建的 ndarray 的新引用,或者如果转换期间发生错误,则 out 将包含 NULL .否则,out 将包含对 Py_NotImplemented 的借用引用,并且不设置任何错误条件.此版本允许在查找 __array__ 属性的数组接口部分中设置 dtype. context 未使用.

int PyArray_IsZeroDim(PyObject *op)#

如果 opPyArray_Type 的一个实例(一个子类)并且有 0 维度,则求值为真.

PyArray_IsScalar(op, cls)#

如果 op 是 Py{cls}ArrType_Type 的一个实例,则求值为真.

int PyArray_CheckScalar(PyObject *op)#

如果 op 是数组标量( PyGenericArrType_Type 的子类型的实例),或者是维度为 0 的 PyArray_Type (的子类)的实例,则求值为真.

int PyArray_IsPythonNumber(PyObject *op)#

如果 op 是内置数值类型(int,float,complex,long,bool)的实例,则求值为真

int PyArray_IsPythonScalar(PyObject *op)#

如果 op 是内置 Python 标量对象 (int,float,complex,bytes,str,long,bool),则求值为真.

int PyArray_IsAnyScalar(PyObject *op)#

如果 op 是 Python 标量对象(参见 PyArray_IsPythonScalar )或数组标量( PyGenericArrType_Type 的子类型的实例),则求值为真.

int PyArray_CheckAnyScalar(PyObject *op)#

如果 op 是 Python 标量对象(参见 PyArray_IsPythonScalar ),数组标量( PyGenericArrType_Type 的子类型的实例)或者维度为 0 的 PyArray_Type 的子类型的实例,则求值为真.

数据类型访问器#

某些描述符属性可能并非始终定义,或者不应或无法直接访问.

在 2.0 版本发生变更: 在 NumPy 2.0 之前,ABI 对于用户 DType 来说是不同的,但没有必要那么大. 这些访问器都是在 2.0 中添加的,可以向后移植(参见 PyArray_Descr 结构已更改 ).

npy_intp PyDataType_ELSIZE(PyArray_Descr *descr)#

数据类型的元素大小(Python 中的 itemsize ).

备注

如果 descr 附加到数组,可以使用 PyArray_ITEMSIZE(arr) ,并且它在所有 NumPy 版本上都可用.

void PyDataType_SET_ELSIZE(PyArray_Descr *descr, npy_intp size)#

允许设置 itemsize,这仅与字符串/字节数据类型相关,因为它是使用新大小定义一个数据类型的当前模式.

npy_intp PyDataType_ALIGNENT(PyArray_Descr *descr)#

数据类型的对齐方式.

PyObject *PyDataType_METADATA(PyArray_Descr *descr)#

附加到 dtype 的元数据,可以是 NULL 或字典.

PyObject *PyDataType_NAMES(PyArray_Descr *descr)#

附加到 dtype 的结构化字段名称的 NULL 或元组.

PyObject *PyDataType_FIELDS(PyArray_Descr *descr)#

NULL , None 或结构化 dtype 字段的 dict,这个 dict 必须不能突变,NumPy 可能会在未来改变字段的存储方式.

这与 np.dtype.fields 返回的 dict 相同.

NpyAuxData *PyDataType_C_METADATA(PyArray_Descr *descr)#

附加到描述符的 C 元数据对象.通常不需要这个访问器.C 元数据字段确实提供了对 datetime/timedelta 时间单位信息的访问.

PyArray_ArrayDescr *PyDataType_SUBARRAY(PyArray_Descr *descr)#

关于子数组 dtype 的信息,相当于 Python 中的 np.dtype.basenp.dtype.shape .

如果这个是非 NULL ,那么这个数据类型描述符是另一种数据类型描述符的 C 风格的连续数组.换句话说,这个描述符描述的每个元素实际上是某个其他基本描述符的数组.这作为另一个数据类型描述符中的字段的数据类型描述符最有用.如果这是非 NULL (但基本描述符的字段成员可以是非 NULL ),则字段成员应为 NULL .

type PyArray_ArrayDescr#
typedef struct {
    PyArray_Descr *base;
    PyObject *shape;
} PyArray_ArrayDescr;
PyArray_Descr *base#

基本类型的数据类型描述符对象.

PyObject *shape#

子数组的形状(始终为 C 风格的连续),以 Python 元组形式表示.

数据类型检查#

对于 typenum 宏,参数是一个表示枚举数组数据类型的整数.对于数组类型检查宏,参数必须是一个 PyObject* ,它可以直接解释为 PyArrayObject* .

int PyTypeNum_ISUNSIGNED(int num)#
int PyDataType_ISUNSIGNED(PyArray_Descr *descr)#
int PyArray_ISUNSIGNED(PyArrayObject *obj)#

类型表示一个无符号整数.

int PyTypeNum_ISSIGNED(int num)#
int PyDataType_ISSIGNED(PyArray_Descr *descr)#
int PyArray_ISSIGNED(PyArrayObject *obj)#

类型表示一个有符号整数.

int PyTypeNum_ISINTEGER(int num)#
int PyDataType_ISINTEGER(PyArray_Descr *descr)#
int PyArray_ISINTEGER(PyArrayObject *obj)#

类型表示任意整数.

int PyTypeNum_ISFLOAT(int num)#
int PyDataType_ISFLOAT(PyArray_Descr *descr)#
int PyArray_ISFLOAT(PyArrayObject *obj)#

类型表示任意浮点数.

int PyTypeNum_ISCOMPLEX(int num)#
int PyDataType_ISCOMPLEX(PyArray_Descr *descr)#
int PyArray_ISCOMPLEX(PyArrayObject *obj)#

类型表示任意复数浮点数.

int PyTypeNum_ISNUMBER(int num)#
int PyDataType_ISNUMBER(PyArray_Descr *descr)#
int PyArray_ISNUMBER(PyArrayObject *obj)#

类型表示任意整数,浮点数或复数浮点数.

int PyTypeNum_ISSTRING(int num)#
int PyDataType_ISSTRING(PyArray_Descr *descr)#
int PyArray_ISSTRING(PyArrayObject *obj)#

类型表示字符串数据类型.

int PyTypeNum_ISFLEXIBLE(int num)#
int PyDataType_ISFLEXIBLE(PyArray_Descr *descr)#
int PyArray_ISFLEXIBLE(PyArrayObject *obj)#

类型表示一个灵活的数组类型 ( NPY_STRING , NPY_UNICODE , 或 NPY_VOID ).

int PyDataType_ISUNSIZED(PyArray_Descr *descr)#

该类型没有附加尺寸信息,可以调整大小. 应该只对灵活的数据类型调用. 附加到数组的类型将始终调整大小,因此该宏的数组形式不存在.

对于没有字段的结构化数据类型,此函数现在返回 False.

int PyTypeNum_ISUSERDEF(int num)#
int PyDataType_ISUSERDEF(PyArray_Descr *descr)#
int PyArray_ISUSERDEF(PyArrayObject *obj)#

类型表示用户定义的类型.

int PyTypeNum_ISEXTENDED(int num)#
int PyDataType_ISEXTENDED(PyArray_Descr *descr)#
int PyArray_ISEXTENDED(PyArrayObject *obj)#

类型是灵活的或用户定义的.

int PyTypeNum_ISOBJECT(int num)#
int PyDataType_ISOBJECT(PyArray_Descr *descr)#
int PyArray_ISOBJECT(PyArrayObject *obj)#

类型表示对象数据类型.

int PyTypeNum_ISBOOL(int num)#
int PyDataType_ISBOOL(PyArray_Descr *descr)#
int PyArray_ISBOOL(PyArrayObject *obj)#

类型表示布尔数据类型.

int PyDataType_HASFIELDS(PyArray_Descr *descr)#
int PyArray_HASFIELDS(PyArrayObject *obj)#

类型具有与之关联的字段.

int PyArray_ISNOTSWAPPED(PyArrayObject *m)#

如果ndarray m的数据区域根据数组的数据类型描述符按机器字节顺序排列,则求值为true.

int PyArray_ISBYTESWAPPED(PyArrayObject *m)#

如果ndarray m的数据区域未根据数组的数据类型描述符按机器字节顺序排列,则求值为true.

npy_bool PyArray_EquivTypes(PyArray_Descr *type1, PyArray_Descr *type2)#

如果 type1 和 type2 实际上代表此平台的等效类型(忽略每种类型的 fortran 成员),则返回 NPY_TRUE . 例如,在 32 位平台上, NPY_LONGNPY_INT 是等效的. 否则返回 NPY_FALSE .

npy_bool PyArray_EquivArrTypes(PyArrayObject *a1, PyArrayObject *a2)#

如果 a1 和 a2 是具有此平台等效类型的数组,则返回 NPY_TRUE .

npy_bool PyArray_EquivTypenums(int typenum1, int typenum2)#

PyArray_EquivTypes (…) 的特殊情况,不接受灵活的数据类型,但可能更容易调用.

int PyArray_EquivByteorders(int b1, int b2)#

如果字节顺序字符 b1 和 b2 ( NPY_LITTLE , NPY_BIG , NPY_NATIVE , NPY_IGNORE ) 相等或等效于其本机字节顺序规范,则为 True. 因此,在小端机器上, NPY_LITTLENPY_NATIVE 是等效的,而在大端机器上它们是不等效的.

转换数据类型#

PyObject *PyArray_Cast(PyArrayObject *arr, int typenum)#

主要用于向后兼容 Numeric C-API 和简单地转换为非灵活类型. 返回一个新的数组对象,其中 arr 的元素被转换为 datatype typenum,它必须是枚举类型之一,而不是灵活类型.

PyObject *PyArray_CastToType(PyArrayObject *arr, PyArray_Descr *type, int fortran)#

返回指定类型的新数组,根据需要转换 arr 的元素. fortran 参数指定输出数组的顺序.

int PyArray_CastTo(PyArrayObject *out, PyArrayObject *in)#

从 1.6 开始,此函数只调用 PyArray_CopyInto ,它处理转换.

将数组 in 中的元素转换为数组 out. 输出数组应该是可写的,具有输入数组中元素数量的整数倍(多个副本可以放置在 out 中),并且具有作为内置类型之一的数据类型. 成功返回 0,如果发生错误则返回 -1.

int PyArray_CanCastSafely(int fromtype, int totype)#

如果可以将数据类型 fromtype 的数组转换为数据类型 totype 的数组而不丢失信息,则返回非零值. 一个例外是允许将 64 位整数转换为 64 位浮点值,即使这可能会丢失大整数的精度,以便在没有明确请求的情况下不会扩散长双精度的使用. 灵活的数组类型不会根据其长度使用此函数进行检查.

int PyArray_CanCastTo(PyArray_Descr *fromtype, PyArray_Descr *totype)#

PyArray_CanCastTypeTo 在 NumPy 1.6 及更高版本中取代了此函数.

等效于 PyArray_CanCastTypeTo(fromtype, totype, NPY_SAFE_CASTING).

int PyArray_CanCastTypeTo(PyArray_Descr *fromtype, PyArray_Descr *totype, NPY_CASTING casting)#

如果可以根据转换规则 casting 将数据类型 fromtype (可以包括灵活类型) 的数组安全地转换为数据类型 totype (可以包括灵活类型) 的数组,则返回非零值. 对于具有 NPY_SAFE_CASTING 的简单类型,这基本上是 PyArray_CanCastSafely 的一个包装器,但对于字符串或 unicode 等灵活类型,它会生成考虑到其大小的结果. 只有在字符串或 unicode 类型足够大以容纳要转换的整数/浮点类型的最大值的情况下,才可以使用 NPY_SAFE_CASTING 将整数和浮点类型转换为字符串或 unicode 类型.

int PyArray_CanCastArrayTo(PyArrayObject *arr, PyArray_Descr *totype, NPY_CASTING casting)#

如果可以根据 casting 中给出的转换规则将 arr 转换为 totype,则返回非零值. 如果 arr 是数组标量,则会考虑其值,并且当该值不会溢出或在转换为较小类型时被截断为整数时,也会返回非零值.

PyArray_Descr *PyArray_MinScalarType(PyArrayObject *arr)#

备注

随着 NumPy 2 中 NEP 50 的采用,此函数在内部不再使用.目前提供它是为了向后兼容,但预计最终会被弃用.

如果 arr 是一个数组,则返回其数据类型描述符;但如果 arr 是一个数组标量(维度为 0),它会找到可以将该值转换为的最小尺寸的数据类型,而不会溢出或截断为整数.

此函数不会将复数降级为浮点数,也不会将任何类型降级为布尔值,但当标量值为正数时,会将有符号整数降级为无符号整数.

PyArray_Descr *PyArray_PromoteTypes(PyArray_Descr *type1, PyArray_Descr *type2)#

查找 type1 和 type2 可以安全转换成的最小尺寸和种类的数据类型.此函数是对称和关联的.字符串或 unicode 结果将是适合存储转换为字符串或 unicode 的输入类型的最大值的大小.

PyArray_Descr *PyArray_ResultType(npy_intp narrs, PyArrayObject **arrs, npy_intp ndtypes, PyArray_Descr **dtypes)#

此函数将类型提升应用于所有输入数组和 dtype 对象,使用 NumPy 规则组合标量和数组,以确定具有给定操作数集合的操作的输出类型.这与 ufunc 生成的结果类型相同.

有关类型提升算法的更多详细信息,请参见 numpy.result_type 的文档.

int PyArray_ObjectType(PyObject *op, int mintype)#

此函数已被 PyArray_ResultType 取代.

此函数对于确定两个或多个数组可以转换为的公共类型很有用.它仅适用于非灵活的数组类型,因为没有传递 itemsize 信息. mintype 参数表示可接受的最小类型,op 表示将转换为数组的对象.返回值是枚举的 typenumber,它表示 op 应具有的数据类型.

PyArrayObject **PyArray_ConvertToCommonType(PyObject *op, int *n)#

此功能在很大程度上已被 1.6 中引入的迭代器 NpyIter 取代,它带有标志 NPY_ITER_COMMON_DTYPE 或所有操作数都具有相同的 dtype 参数.

将 op 中包含的 Python 对象序列转换为每个都具有相同数据类型的 ndarray 数组.类型的选择方式与 PyArray_ResultType 相同.序列的长度在 n 中返回,并且 PyArrayObject 指针的 n 长度数组是返回值(如果发生错误,则为 NULL ).返回的数组必须由此例程的调用者释放(使用 PyDataMem_FREE ),并且其中的所有数组对象都必须 DECREF ,否则会发生内存泄漏.下面的示例模板代码显示了一个典型的用法:

mps = PyArray_ConvertToCommonType(obj, &n);
if (mps==NULL) return NULL;
{code}
<before return>
for (i=0; i<n; i++) Py_DECREF(mps[i]);
PyDataMem_FREE(mps);
{return}
char *PyArray_Zero(PyArrayObject *arr)#

指向新创建的内存的指针,其大小为 arr ->itemsize,其中保存了该类型的 0 的表示形式.当不再需要时,必须使用 PyDataMem_FREE (ret) 释放返回的指针 ret.

char *PyArray_One(PyArrayObject *arr)#

指向新创建的内存的指针,其大小为 arr ->itemsize,其中保存了该类型的 1 的表示形式.当不再需要时,必须使用 PyDataMem_FREE (ret) 释放返回的指针 ret.

int PyArray_ValidType(int typenum)#

如果 typenum 表示有效类型编号(内置,用户定义或字符代码),则返回 NPY_TRUE .否则,此函数返回 NPY_FALSE .

用户定义的数据类型#

void PyArray_InitArrFuncs(PyArray_ArrFuncs *f)#

将所有函数指针和成员初始化为 NULL .

int PyArray_RegisterDataType(PyArray_DescrProto *dtype)#

备注

从 NumPy 2.0 开始,此 API 被认为是遗留的,新的 DType API 更强大,并提供了额外的灵活性.该 API 最终可能会被弃用,但目前仍继续提供支持.

为 NumPy 1.x 和 2.x 编译

NumPy 2.x 需要传入一个 PyArray_DescrProto 类型的结构,而不是 PyArray_Descr .这对于允许更改是必要的.为了使代码在 1.x 和 2.x 上都能运行和编译,您需要将结构的类型更改为 PyArray_DescrProto 并添加:

/* Allow compiling on NumPy 1.x */
#if NPY_ABI_VERSION < 0x02000000
#define PyArray_DescrProto PyArray_Descr
#endif

用于 1.x 兼容性. 此外,该结构将不再是实际的描述符,只会更新其类型编号.成功注册后,您必须通过以下方式获取实际的 dtype:

int type_num = PyArray_RegisterDataType(&my_descr_proto);
if (type_num < 0) {
    /* error */
}
PyArray_Descr *my_descr = PyArray_DescrFromType(type_num);

通过这两个更改,代码应该可以在 1.x 和 2.x 或更高版本上编译和工作.

在不太可能的情况下,如果您正在堆分配 dtype 结构,则应在 NumPy 2 上再次释放它,因为会创建一个副本.该结构不是有效的 Python 对象,因此不要对其使用 Py_DECREF .

将数据类型注册为数组的新用户定义数据类型.该类型必须填写大部分条目.这并非总是经过检查,错误可能会导致段错误.特别是, dtype 结构的 typeobj 成员必须填充一个 Python 类型,该类型具有与 dtype 的 elsize 成员相对应的固定大小的元素大小.同样, f 成员必须具有必需的函数:nonzero,copyswap,copyswapn,getitem,setitem 和 cast(如果不需要支持,某些 cast 函数可能为 NULL ).为避免混淆,您应该选择唯一的字符类型代码,但这不会强制执行,也不会在内部依赖.

返回用户定义的类型编号,该编号唯一标识该类型.然后可以使用返回的类型编号从 PyArray_DescrFromType 获取指向新结构的指针.如果发生错误,则返回 -1.如果此 dtype 已注册(仅通过指针的地址检查),则返回先前分配的类型编号.

numpy 已知的用户 DType 的数量存储在 NPY_NUMUSERTYPES 中,这是一个在 C API 中公开的静态全局变量.访问此符号本质上不是线程安全的.如果由于某种原因需要在多线程上下文中使用此 API,则需要添加自己的锁定,NumPy 不保证可以以线程安全的方式添加新数据类型.

int PyArray_RegisterCastFunc(PyArray_Descr *descr, int totype, PyArray_VectorUnaryFunc *castfunc)#

注册一个底层转换函数 castfunc,以将数据类型 descr 转换为给定的数据类型编号 totype.任何旧的转换函数都会被覆盖.成功时返回 0 ,失败时返回 -1 .

type PyArray_VectorUnaryFunc#

底层转换函数的函数指针类型.

int PyArray_RegisterCanCast(PyArray_Descr *descr, int totype, NPY_SCALARKIND scalar)#

将数据类型编号 totype 注册为可从给定标量类型的 dtype 对象 descr 转换.使用 scalar = NPY_NOSCALAR 注册数据类型 descr 的数组可以安全地转换为类型编号为 totype 的数据类型.返回值是成功时为 0,失败时为 -1.

NPY_OBJECT 的特殊函数#

警告

当处理填充了对象的数组或缓冲区时,NumPy 会尝试确保在读取任何数据之前,此类缓冲区都填充了 None .但是,可能存在仅初始化为 NULL 的数组的代码路径.NumPy 本身接受 NULL 作为 None 的别名,但在调试模式下编译时可能会 assertNULL .

由于 NumPy 在使用 None 初始化方面尚未保持一致,因此用户在处理 NumPy 创建的缓冲区时必须期望值为 NULL .用户还应确保将完全初始化的缓冲区传递给 NumPy,因为 NumPy 将来可能会对此提出严格要求.

目前,目标是确保 NumPy 始终在读取对象数组之前对其进行初始化.任何未能这样做的情况都将被视为错误.将来,用户在从任何数组读取数据时可能能够依赖非 NULL 值,但对新创建数组的写入可能仍然存在例外(例如,ufunc 代码中的输出数组).截至 NumPy 1.23,已知存在未正确填充的已知代码路径.

int PyArray_INCREF(PyArrayObject *op)#

用于包含任何 Python 对象的数组 op.它根据 op 的数据类型增加数组中每个对象的引用计数.如果发生错误,则返回 -1,否则返回 0.

void PyArray_Item_INCREF(char *ptr, PyArray_Descr *dtype)#

用于根据数据类型 dtype 在位置 ptr 处 INCREF 所有对象的函数.如果 ptr 是一个结构化类型的开头,并且在任何偏移量处都有一个对象,那么这将(递归地)增加结构化类型中所有类似对象项的引用计数.

int PyArray_XDECREF(PyArrayObject *op)#

用于包含任何 Python 对象的数组 op.它根据 op 的数据类型减少数组中每个对象的引用计数.正常返回值是 0.如果发生错误,则返回 -1.

void PyArray_Item_XDECREF(char *ptr, PyArray_Descr *dtype)#

用于 XDECREF 位于位置 ptr 处的所有类对象项的函数,如数据类型 dtype 中记录的那样.这是递归工作的,因此如果 dtype 本身具有包含类似对象项的数据类型的字段,则所有类似对象的字段都将 XDECREF 'd .

int PyArray_SetWritebackIfCopyBase(PyArrayObject *arr, PyArrayObject *base)#

前提条件: arrbase 的副本(尽管可能具有不同的步幅,顺序等).设置 NPY_ARRAY_WRITEBACKIFCOPY 标志和 arr->base ,并将 base 设置为 READONLY.在调用 PyArray_ResolveWritebackIfCopy 之前调用 Py_DECREF ,以便将任何更改复制回 base 并重置 READONLY 标志.

成功返回 0,失败返回 -1.

数组标志#

PyArrayObject 结构的 flags 属性包含有关数组使用的内存(由 data 成员指向)的重要信息.此标志信息必须保持准确,否则可能会导致奇怪的结果,甚至导致段错误.

有 6 个(二进制)标志描述了数据缓冲区使用的内存区域.这些常量在 arrayobject.h 中定义,并确定标志的位位置. Python 公开了一个不错的基于属性的接口以及一个类似字典的接口,用于获取(并在适当的情况下,设置)这些标志.

各种类型的内存区域都可以被 ndarray 指向,因此需要这些标志.如果在 C 代码中获取任意的 PyArrayObject ,您需要了解设置的标志.如果需要保证某种类型的数组(例如 NPY_ARRAY_C_CONTIGUOUSNPY_ARRAY_BEHAVED ),则将这些要求传递给 PyArray_FromAny 函数.

在 NumPy 的 1.6 及更早版本中,以下标志没有 _ARRAY_ 宏命名空间.从 1.7 开始,常量名称的这种形式已被弃用.

基本数组标志#

ndarray 可以拥有一个数据段,该数据段不是您可以操作的简单的连续的,行为良好的内存块.它可能没有与字边界对齐(在某些平台上非常重要).它的数据字节顺序可能与机器识别的顺序不同.它可能不可写.它可能采用 Fortran 连续顺序.数组标志用于指示可以说明与数组关联的哪些数据.

NPY_ARRAY_C_CONTIGUOUS#

数据区采用 C 风格的连续顺序(最后一个索引变化最快).

NPY_ARRAY_F_CONTIGUOUS#

数据区采用 Fortran 风格的连续顺序(第一个索引变化最快).

备注

数组可以同时采用 C 风格和 Fortran 风格的连续顺序.这对于一维数组来说很明显,但对于更高维的数组来说也可能是真的.

即使对于连续数组,如果 arr.shape[dim] == 1 或数组没有元素,则给定维度 arr.strides[dim] 的步幅也可能是任意的.对于 C 风格的连续数组,通常不成立 self.strides[-1] == self.itemsize ,对于 Fortran 风格的连续数组,通常不成立 self.strides[0] == self.itemsize .从 C API 访问数组的 itemsize 的正确方法是 PyArray_ITEMSIZE(arr) .

NPY_ARRAY_OWNDATA#

数据区由此数组拥有.永远不要手动设置,而是创建一个包装数据的 PyObject 并将数组的 base 设置为该对象.例如,参见 test_mem_policy 中的测试.

NPY_ARRAY_ALIGNED#

数据区和所有数组元素都已正确对齐.

NPY_ARRAY_WRITEABLE#

数据区可以写入.

请注意,以上 3 个标志的定义方式是,新的,行为良好的数组会将这些标志定义为 true.

NPY_ARRAY_WRITEBACKIFCOPY#

数据区表示一个(行为良好的)副本,当调用 PyArray_ResolveWritebackIfCopy 时,其信息应传输回原始数据.

这是一个特殊的标志,如果此数组表示一个副本,该副本是因为用户在 PyArray_FromAny 中需要某些标志,并且必须复制其他一些数组(并且用户要求在此类情况下设置此标志)而创建的.然后,base 属性指向"行为不当"的数组(设置为 read_only). PyArray_ResolveWritebackIfCopy 会将其内容复制回"行为不当"的数组(必要时进行强制转换),并将"行为不当"的数组重置为 NPY_ARRAY_WRITEABLE .如果"行为不当"的数组一开始就不是 NPY_ARRAY_WRITEABLE ,那么 PyArray_FromAny 将返回一个错误,因为 NPY_ARRAY_WRITEBACKIFCOPY 将是不可能的.

PyArray_UpdateFlags (obj, flags) 将更新 obj->flags ,其中 flags 可以是 NPY_ARRAY_C_CONTIGUOUS , NPY_ARRAY_F_CONTIGUOUS , NPY_ARRAY_ALIGNEDNPY_ARRAY_WRITEABLE 中的任何一个.

数组标志的组合#

NPY_ARRAY_BEHAVED#

NPY_ARRAY_ALIGNED | NPY_ARRAY_WRITEABLE

NPY_ARRAY_CARRAY#

NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_BEHAVED

NPY_ARRAY_CARRAY_RO#

NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_ALIGNED

NPY_ARRAY_FARRAY#

NPY_ARRAY_F_CONTIGUOUS | NPY_ARRAY_BEHAVED

NPY_ARRAY_FARRAY_RO#

NPY_ARRAY_F_CONTIGUOUS | NPY_ARRAY_ALIGNED

NPY_ARRAY_DEFAULT#

NPY_ARRAY_CARRAY

NPY_ARRAY_IN_ARRAY#

NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_ALIGNED

NPY_ARRAY_IN_FARRAY#

NPY_ARRAY_F_CONTIGUOUS | NPY_ARRAY_ALIGNED

NPY_ARRAY_OUT_ARRAY#

NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_WRITEABLE | NPY_ARRAY_ALIGNED

NPY_ARRAY_OUT_FARRAY#

NPY_ARRAY_F_CONTIGUOUS | NPY_ARRAY_WRITEABLE | NPY_ARRAY_ALIGNED

NPY_ARRAY_INOUT_ARRAY#

NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_WRITEABLE | NPY_ARRAY_ALIGNED | NPY_ARRAY_WRITEBACKIFCOPY

NPY_ARRAY_INOUT_FARRAY#

NPY_ARRAY_F_CONTIGUOUS | NPY_ARRAY_WRITEABLE | NPY_ARRAY_ALIGNED | NPY_ARRAY_WRITEBACKIFCOPY

NPY_ARRAY_UPDATE_ALL#

NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_F_CONTIGUOUS | NPY_ARRAY_ALIGNED

类似标志的常量#

这些常量在 PyArray_FromAny (及其宏形式) 中使用,以指定新数组的所需属性.

NPY_ARRAY_FORCECAST#

转换为所需的类型,即使这样做会丢失信息.

NPY_ARRAY_ENSURECOPY#

确保生成的数组是原始数组的副本.

NPY_ARRAY_ENSUREARRAY#

确保生成的对象是一个实际的 ndarray,而不是一个子类.

这些常量在 PyArray_CheckFromAny (及其宏形式) 中使用,以指定新数组的所需属性.

NPY_ARRAY_NOTSWAPPED#

确保返回的数组具有以机器字节顺序排列的数据类型描述符,从而覆盖 dtype 参数中的任何规范.通常,字节顺序要求由 dtype 参数确定.如果设置了此标志,并且 dtype 参数未指示机器字节顺序描述符(或者为 NULL 且对象已经是具有非机器字节顺序的数据类型描述符的数组),则将创建一个新的数据类型描述符,并将其字节顺序字段设置为本机.

NPY_ARRAY_BEHAVED_NS#

NPY_ARRAY_ALIGNED | NPY_ARRAY_WRITEABLE | NPY_ARRAY_NOTSWAPPED

NPY_ARRAY_ELEMENTSTRIDES#

确保返回的数组的步幅是元素大小的倍数.

标志检查#

对于所有这些宏,arr 必须是 PyArray_Type 的(子类)实例.

int PyArray_CHKFLAGS(const PyArrayObject *arr, int flags)#

第一个参数 arr 必须是 ndarray 或子类.参数 flags 应该是一个整数,由数组可以具有的可能标志的按位组合组成 NPY_ARRAY_C_CONTIGUOUS , NPY_ARRAY_F_CONTIGUOUS , NPY_ARRAY_OWNDATA , NPY_ARRAY_ALIGNED , NPY_ARRAY_WRITEABLE , NPY_ARRAY_WRITEBACKIFCOPY .

int PyArray_IS_C_CONTIGUOUS(const PyArrayObject *arr)#

如果 arr 是 C 风格的连续的,则求值为真.

int PyArray_IS_F_CONTIGUOUS(const PyArrayObject *arr)#

如果 arr 是 Fortran 风格的连续的,则求值为真.

int PyArray_ISFORTRAN(const PyArrayObject *arr)#

如果 arr 是 Fortran 风格的连续的,而不是 C 风格的连续的,则求值为真. PyArray_IS_F_CONTIGUOUS 是测试 Fortran 风格连续性的正确方法.

int PyArray_ISWRITEABLE(const PyArrayObject *arr)#

如果 arr 的数据区域可以写入,则求值为真

int PyArray_ISALIGNED(const PyArrayObject *arr)#

如果 arr 的数据区域在机器上正确对齐,则求值为真.

int PyArray_ISBEHAVED(const PyArrayObject *arr)#

如果 arr 的数据区域根据其描述符对齐,可写且以机器字节顺序排列,则求值为真.

int PyArray_ISBEHAVED_RO(const PyArrayObject *arr)#

如果 arr 的数据区域已对齐且以机器字节顺序排列,则求值为真.

int PyArray_ISCARRAY(const PyArrayObject *arr)#

如果 arr 的数据区域是 C 风格的连续的,并且 PyArray_ISBEHAVED (arr) 为真,则求值为真.

int PyArray_ISFARRAY(const PyArrayObject *arr)#

如果 arr 的数据区域是 Fortran 风格的连续的,并且 PyArray_ISBEHAVED (arr) 为真,则求值为真.

int PyArray_ISCARRAY_RO(const PyArrayObject *arr)#

如果 arr 的数据区域是 C 风格的连续的,对齐的且以机器字节顺序排列,则求值为真.

int PyArray_ISFARRAY_RO(const PyArrayObject *arr)#

如果 arr 的数据区域是 Fortran 风格的连续的,对齐的且以机器字节顺序排列,则求值为真.

int PyArray_ISONESEGMENT(const PyArrayObject *arr)#

如果 arr 的数据区域由单个(C 风格或 Fortran 风格)连续段组成,则求值为真.

void PyArray_UpdateFlags(PyArrayObject *arr, int flagmask)#

可以从数组对象本身"计算" NPY_ARRAY_C_CONTIGUOUS , NPY_ARRAY_ALIGNEDNPY_ARRAY_F_CONTIGUOUS 数组标志.此例程通过执行所需的计算来更新 arr 的一个或多个这些标志,如 flagmask 中指定.

警告

重要的是保持标志更新(使用 PyArray_UpdateFlags 可以帮助),只要对数组执行可能导致它们更改的操作.NumPy 中稍后依赖于这些标志状态的计算不会重复计算来更新它们.

int PyArray_FailUnlessWriteable(PyArrayObject *obj, const char *name)#

如果 obj 可写,则此函数不执行任何操作并返回 0.如果 obj 不可写,则会引发异常并返回 -1.它也可能执行其他内务处理,例如在转换为视图的数组上发出警告.在写入数组之前,始终在某个时间点调用此函数.

name 是数组的名称,用于提供更好的错误消息.它可以是"赋值目标","输出数组",甚至只是"数组"之类的东西.

ArrayMethod API#

ArrayMethod 循环旨在作为一种通用机制,用于编写数组上的循环,包括 ufunc 循环和转换.公共 API 在 numpy/dtype_api.h 标头中定义.有关 ArrayMethod API 中公开的 C 结构的文档,请参阅 PyArrayMethod_Context 和 PyArrayMethod_Spec .

槽与类型定义#

这些用于标识 ArrayMethod 槽实现的是哪种函数.有关每个槽必须实现的函数的文档,请参见下文的 槽与类型定义 .

NPY_METH_resolve_descriptors#
typedef NPY_CASTING (PyArrayMethod_ResolveDescriptors)(struct PyArrayMethodObject_tag *method, PyArray_DTypeMeta *const *dtypes, PyArray_Descr *const *given_descrs, PyArray_Descr **loop_descrs, npy_intp *view_offset)#

该函数用于根据操作数的描述符设置操作的描述符. 例如,一个具有两个输入操作数和一个输出操作数的 ufunc 操作,在没有在 python API 中设置 out 的情况下被调用, resolve_descriptors 将被传递两个操作数的描述符,并根据为 ArrayMethod 设置的输出 DType 确定用于输出的正确描述符. 如果设置了 out ,那么输出描述符也将被传入,并且不应该被覆盖.

该方法是指向底层强制转换或 ufunc 循环的指针. 未来我们可能会公开这个结构体,但目前这是一个不透明的指针,无法检查该方法. dtypes 是一个长度为 nargsPyArray_DTypeMeta 指针数组,given_descrs 是一个长度为 nargs 的输入描述符实例数组(如果用户没有提供输出,则输出描述符可能为 NULL),loop_descrs 是一个长度为 nargs 的描述符数组,必须由 resolve descriptors 实现填充. view_offset 当前仅对强制转换有效,通常可以忽略. 当强制转换不需要任何操作时,可以通过将 view_offset 设置为 0 来发出信号. 如果出错,您必须返回 (NPY_CASTING)-1 并设置错误.

NPY_METH_strided_loop#
NPY_METH_contiguous_loop#
NPY_METH_unaligned_strided_loop#
NPY_METH_unaligned_contiguous_loop#

实现行为(ufunc 或强制转换)的一维跨步循环.在大多数情况下, NPY_METH_strided_loop 是通用且唯一需要实现的版本. NPY_METH_contiguous_loop 可以额外实现为更轻量级/更快的版本,并且当所有输入和输出都是连续的时使用.

为了处理可能未对齐的数据,NumPy 需要能够将未对齐的数据复制到对齐的数据. 在实现新的 DType 时,它的”强制转换”或复制需要实现 NPY_METH_unaligned_strided_loop . 与普通版本不同,此循环不得假定可以以对齐的方式访问数据. 这些循环必须在访问或存储之前复制每个值:

type_in in_value;
type_out out_value
memcpy(&value, in_data, sizeof(type_in));
out_value = in_value;
memcpy(out_data, &out_value, sizeof(type_out)

而普通循环可以只使用:

*(type_out *)out_data = *(type_in)in_data;

未对齐的循环当前仅在强制转换中使用,并且永远不会在 ufunc 中选择(ufunc 创建临时副本以确保对齐的输入). 当定义了 NPY_METH_get_loop 时,这些槽 ID 会被忽略,而是使用 get_loop 函数返回的任何循环.

NPY_METH_contiguous_indexed_loop#

一种专门的内部循环选项,用于加速常见的 ufunc.at 计算.

typedef int (PyArrayMethod_StridedLoop)(PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, const npy_intp *strides, NpyAuxData *auxdata)#

ArrayMethod 循环的实现. 上面列出的所有循环槽 ID 都必须提供 PyArrayMethod_StridedLoop 实现. context 是一个包含循环操作上下文的结构体,特别是输入描述符. data 是指向输入和输出数组缓冲区开头的指针数组. dimensions 是操作的循环维度. strides 是一个长度为 nargs 的数组,表示每个输入的步长. auxdata 是一组可选的辅助数据,可以传递到循环中 - 有助于打开和关闭可选行为,或通过允许类似的 ufunc 共享循环实现或分配在多个跨步循环调用中持久存在的空间来减少样板.

NPY_METH_get_loop#

允许更细粒度地控制循环选择. 接受 PyArrayMethod_GetLoop 的实现,后者又返回一个跨步循环实现. 如果定义了 NPY_METH_get_loop ,则忽略其他循环槽 ID(如果已指定).

typedef int (PyArrayMethod_GetLoop)(PyArrayMethod_Context *context, int aligned, int move_references, const npy_intp *strides, PyArrayMethod_StridedLoop **out_loop, NpyAuxData **out_transferdata, NPY_ARRAYMETHOD_FLAGS *flags);#

在运行时设置用于操作的循环. context 是操作的运行时上下文. aligned 指示循环的数据访问是对齐 (1) 还是未对齐 (0). move_references 指示是否应复制数据中嵌入的引用. strides 是输入数组的步长,out_loop 是一个指针,必须使用指向循环实现的指针填充. 可以选择填充 out_transferdata 以允许将额外的用户定义的上下文传递给操作. flags 必须使用与操作相关的 ArrayMethod 标志填充. 例如,这对于指示内部循环是否需要保持 Python GIL 是必要的.

NPY_METH_get_reduction_initial#
typedef int (PyArrayMethod_GetReductionInitial)(PyArrayMethod_Context *context, npy_bool reduction_is_empty, char *initial)#

查询用于归约的初始值的 ArrayMethod.上下文是 ArrayMethod 上下文,主要用于访问输入描述符. reduction_is_empty 指示归约是否为空.如果为空,则返回的值可能会有所不同.在这种情况下,它是一个"默认"值,可能与通常使用的"标识"值不同.例如:

  • 0.0sum([]) 的默认值.但是 -0.0 在其他情况下是正确的标识,因为它保留了 sum([-0.0]) 的符号.

  • 我们不使用对象的标识,但为空的 sum([], dtype=object)prod([], dtype=object) 返回默认值 01 . 这允许 np.sum(np.array(["a", "b"], dtype=object)) 工作.

  • -infINT_MIN 对于 max 来说是一个标识,但至少 INT_MIN 在没有项目时不是一个好的默认值.

initial 是指向初始值数据的指针,应填充该数据.返回 -1,0 或 1,表示错误,无初始值以及成功填充了初始值.当不需要初始值时,不能给出错误,因为 NumPy 可能会在并非绝对必要的情况下调用它.

标志#

enum NPY_ARRAYMETHOD_FLAGS#

这些标志允许为 ArrayMethod 循环开启和关闭自定义运行时行为. 例如,如果 ufunc 不可能触发浮点错误,则在注册 ufunc 时,应在 ufunc 上设置 NPY_METH_NO_FLOATINGPOINT_ERRORS 标志.

enumerator NPY_METH_REQUIRES_PYAPI#

指示该方法必须持有 GIL. 如果未设置此标志,则在调用循环之前释放 GIL.

enumerator NPY_METH_NO_FLOATINGPOINT_ERRORS#

指示该方法不会生成浮点错误,因此可以跳过在循环完成后检查浮点错误.

enumerator NPY_METH_SUPPORTS_UNALIGNED#

指示该方法支持非对齐访问.

enumerator NPY_METH_IS_REORDERABLE#

指示重复应用循环的结果(例如,在归约运算中)不依赖于应用顺序.

enumerator NPY_METH_RUNTIME_FLAGS#

可以在运行时更改的标志.

类型定义#

下面描述了 ArrayMethod API 用户可以实现的函数的类型定义.

typedef int (PyArrayMethod_TraverseLoop)(void *traverse_context, const PyArray_Descr *descr, char *data, npy_intp size, npy_intp stride, NpyAuxData *auxdata)#

在单个数组上工作的遍历循环. 这类似于通用跨步循环函数. 这专为需要访问单个数组的每个元素的循环而设计.

目前,它通过 NPY_DT_get_clear_loop DType API 钩子用于数组清除,并通过 NPY_DT_get_fill_zero_loop DType API 钩子用于零填充. 这些对于处理存储嵌入式 Python 对象引用或堆分配数据的数组最有用.

descr 是数组的描述符,data 是指向数组缓冲区的指针,size 是数组缓冲区的 1D 大小,stride 是步幅,auxdata 是循环的可选额外数据.

traverse_context 被传入是因为将来我们可能需要传入解释器状态或类似的状态,但我们不想传入完整的上下文(其中包含指向 dtype,方法,调用者的指针,这些对于遍历函数都没有意义). 我们现在假设将来可以简单地传递此上下文(对于结构化 dtype).

typedef int (PyArrayMethod_GetTraverseLoop)(void *traverse_context, const PyArray_Descr *descr, int aligned, npy_intp fixed_stride, PyArrayMethod_TraverseLoop **out_loop, NpyAuxData **out_auxdata, NPY_ARRAYMETHOD_FLAGS *flags)#

特定于 dtype 遍历的简化 get_loop 函数

它应该设置遍历循环所需的标志,并将 out_loop 设置为循环函数,该函数必须是有效的 PyArrayMethod_TraverseLoop 指针. 目前,它用于零填充和清除存储嵌入式引用的数组.

API 函数和类型定义#

这些函数是主 numpy 数组 API 的一部分,并且与 ArrayMethod API 的其余部分一起添加.

int PyUFunc_AddLoopFromSpec(PyObject *ufunc, PyArrayMethod_Spec *spec)#

直接从给定的 ArrayMethod 规范将循环添加到 ufunc. 主要的 ufunc 注册函数. 这会将新的实现/循环添加到 ufunc. 它替换 PyUFunc_RegisterLoopForType .

int PyUFunc_AddPromoter(PyObject *ufunc, PyObject *DType_tuple, PyObject *promoter)#

请注意,除非输出 dtype 也是签名的一部分,否则当前输出 dtype 始终为 NULL . 这是一个实现细节,将来可能会更改. 但是,通常,promoter 不需要输出 dtype. 注册 ufunc 的新 promoter. 第一个参数是注册 promoter 的 ufunc. 第二个参数是包含与 ufunc 的输入和输出数量匹配的 DType 或 None 的 Python 元组. 最后一个参数是一个 promoter,它存储在 PyCapsule 中. 它被传递操作和请求的 DType 签名,并且可以对其进行突变,以尝试搜索匹配的循环/promoter.

typedef int (PyArrayMethod_PromoterFunction)(PyObject *ufunc, PyArray_DTypeMeta *const op_dtypes[], PyArray_DTypeMeta *const signature[], PyArray_DTypeMeta *new_op_dtypes[])#

启动函数的类型,必须被包装成一个名为 "numpy._ufunc_promoter"PyCapsule .它被传递运算和请求的 DType 签名,并且可以改变签名,以尝试搜索一个新的循环或启动函数,该循环或启动函数可以通过将输入转换为"提升的" DType 来完成运算.

int PyUFunc_GiveFloatingpointErrors(const char *name, int fpe_errors)#

在执行浮点运算后,以一种考虑到通过 numpy.errstate 配置的错误信号的方式检查浮点错误.接受要在错误消息中使用的操作名称和一个整数标志,该标志是 NPY_FPE_DIVIDEBYZERO , NPY_FPE_OVERFLOW , NPY_FPE_UNDERFLOW , NPY_FPE_INVALID 之一,以指示要检查哪个错误.

失败时返回 -1(引发了错误),成功时返回 0.

int PyUFunc_AddWrappingLoop(PyObject *ufunc_obj, PyArray_DTypeMeta *new_dtypes[], PyArray_DTypeMeta *wrapped_dtypes[], PyArrayMethod_TranslateGivenDescriptors *translate_given_descrs, PyArrayMethod_TranslateLoopDescriptors *translate_loop_descrs)#

允许在现有 ufunc 循环周围创建相当轻量级的包装器.这个想法主要用于单元,因为目前它有点受限制,因为它强制您不能使用来自另一个 ufunc 的循环.

typedef int (PyArrayMethod_TranslateGivenDescriptors)(int nin, int nout, PyArray_DTypeMeta *wrapped_dtypes[], PyArray_Descr *given_descrs[], PyArray_Descr *new_descrs[]);#

用于转换给定描述符(传递给 resolve_descriptors )并为包装的循环转换它们的函数.新的描述符必须与旧的描述符可见,必须支持 NULL (对于输出参数),并且通常应该转发.

此函数的输出将用于构造参数的视图,就像它们是被转换的 dtypes 一样,并且不使用强制转换.这意味着这种机制主要适用于"包装"另一个 DType 实现的 DType.例如,一个 unit DType 可以使用它来包装一个现有的浮点 DType,而无需重新实现底层 ufunc 逻辑.在单元示例中, resolve_descriptors 将处理从输入单元计算输出单元.

typedef int (PyArrayMethod_TranslateLoopDescriptors)(int nin, int nout, PyArray_DTypeMeta *new_dtypes[], PyArray_Descr *given_descrs[], PyArray_Descr *original_descrs[], PyArray_Descr *loop_descrs[]);#

用于将实际循环描述符(由原始 resolve_descriptors 函数返回)转换为输出数组应使用的描述符的函数.此函数必须返回"可查看"的类型,它不能以任何会破坏内部循环逻辑的形式对其进行更改.不需要支持 NULL.

包装循环示例#

假设你想为 WrappedDoubleDType 包装 float64 乘法实现.你可以像这样添加一个包装循环:

PyArray_DTypeMeta *orig_dtypes[3] = {
    &WrappedDoubleDType, &WrappedDoubleDType, &WrappedDoubleDType};
PyArray_DTypeMeta *wrapped_dtypes[3] = {
     &PyArray_Float64DType, &PyArray_Float64DType, &PyArray_Float64DType}

PyObject *mod = PyImport_ImportModule("numpy");
if (mod == NULL) {
    return -1;
}
PyObject *multiply = PyObject_GetAttrString(mod, "multiply");
Py_DECREF(mod);

if (multiply == NULL) {
    return -1;
}

int res = PyUFunc_AddWrappingLoop(
    multiply, orig_dtypes, wrapped_dtypes, &translate_given_descrs
    &translate_loop_descrs);

Py_DECREF(multiply);

请注意,这还需要在上面的代码中定义两个函数:

static int
translate_given_descrs(int nin, int nout,
                       PyArray_DTypeMeta *NPY_UNUSED(wrapped_dtypes[]),
                       PyArray_Descr *given_descrs[],
                       PyArray_Descr *new_descrs[])
{
    for (int i = 0; i < nin + nout; i++) {
        if (given_descrs[i] == NULL) {
            new_descrs[i] = NULL;
        }
        else {
            new_descrs[i] = PyArray_DescrFromType(NPY_DOUBLE);
        }
    }
    return 0;
}

static int
translate_loop_descrs(int nin, int NPY_UNUSED(nout),
                      PyArray_DTypeMeta *NPY_UNUSED(new_dtypes[]),
                      PyArray_Descr *given_descrs[],
                      PyArray_Descr *original_descrs[],
                      PyArray_Descr *loop_descrs[])
{
    // more complicated parametric DTypes may need to
    // to do additional checking, but we know the wrapped
    // DTypes *have* to be float64 for this example.
    loop_descrs[0] = PyArray_DescrFromType(NPY_FLOAT64);
    Py_INCREF(loop_descrs[0]);
    loop_descrs[1] = PyArray_DescrFromType(NPY_FLOAT64);
    Py_INCREF(loop_descrs[1]);
    loop_descrs[2] = PyArray_DescrFromType(NPY_FLOAT64);
    Py_INCREF(loop_descrs[2]);
}

用于调用数组方法的 API#

转换#

PyObject *PyArray_GetField(PyArrayObject *self, PyArray_Descr *dtype, int offset)#

等价于 ndarray.getfield (self, dtype, offset).此函数 steals a referencePyArray_Descr 并且返回一个使用当前数组中指定 offset 字节处的数据的给定 dtype 的新数组. offset 加上新数组类型的 itemsize 必须小于 self->descr->elsize ,否则会引发错误.使用与原始数组相同的形状和步长.因此,此函数具有从结构化数组返回字段的效果.但是,它也可以用于从任何数组类型中选择特定的字节或字节组.

int PyArray_SetField(PyArrayObject *self, PyArray_Descr *dtype, int offset, PyObject *val)#

等价于 ndarray.setfield (self, val, dtype, offset ).将从 offset 字节开始和给定 dtype 的字段设置为 val.offset 加上 dtype ->elsize 必须小于 self ->descr->elsize,否则会引发错误.否则,val 参数将被转换为数组并复制到指向的字段中.如有必要,val 的元素会被重复以填充目标数组,但是目标数组中的元素数量必须是 val 中元素数量的整数倍.

PyObject *PyArray_Byteswap(PyArrayObject *self, npy_bool inplace)#

等价于 ndarray.byteswap (self, inplace).返回一个数据区域被字节交换的数组.如果 inplace 为非零,则进行原地字节交换并返回对 self 的引用.否则,创建一个字节交换的副本并保持 self 不变.

PyObject *PyArray_NewCopy(PyArrayObject *old, NPY_ORDER order)#

等价于 ndarray.copy (self, fortran).制作旧数组的副本.返回的数组始终是对齐的和可写的,数据以与旧数组相同的方式解释.如果 order 是 NPY_CORDER ,则返回一个 C 风格的连续数组.如果 order 是 NPY_FORTRANORDER ,则返回一个 Fortran 风格的连续数组.如果 order 是 NPY_ANYORDER ,则仅当旧数组是 Fortran 风格的连续数组时,返回的数组才是 Fortran 风格的连续数组;否则,它是 C 风格的连续数组.

PyObject *PyArray_ToList(PyArrayObject *self)#

等价于 ndarray.tolist (self). 从 self 返回一个嵌套的 Python 列表.

PyObject *PyArray_ToString(PyArrayObject *self, NPY_ORDER order)#

等价于 ndarray.tobytes (self, order). 以 Python 字符串形式返回此数组的字节.

PyObject *PyArray_ToFile(PyArrayObject *self, FILE *fp, char *sep, char *format)#

以 C 风格的连续方式将 self 的内容写入文件指针 fp. 如果 sep 字符串为 “”或 NULL ,则将数据写入为二进制字节. 否则,使用 sep 字符串作为项分隔符,将 self 的内容写入为文本. 每个项都将被打印到文件中. 如果格式化字符串不是 NULL 或 “”,则它是一个 Python print 语句格式化字符串,显示如何写入这些项.

int PyArray_Dump(PyObject *self, PyObject *file, int protocol)#

将 self 中的对象 pickle 到给定的文件(字符串或 Python 文件对象). 如果 file 是一个 Python 字符串,则它被认为是文件名,然后以二进制模式打开. 使用给定的 protocol(如果 protocol 为负数,则使用最高可用协议). 这是 cPickle.dump(self, file, protocol) 的一个简单包装器.

PyObject *PyArray_Dumps(PyObject *self, int protocol)#

将 self 中的对象 pickle 到 Python 字符串并返回. 使用提供的 Pickle 协议(如果 protocol 为负数,则使用最高可用协议).

int PyArray_FillWithScalar(PyArrayObject *arr, PyObject *obj)#

使用给定的标量对象 obj 填充数组 arr. 该对象首先被转换为 arr 的数据类型,然后复制到每个位置. 如果发生错误,则返回 -1,否则返回 0.

PyObject *PyArray_View(PyArrayObject *self, PyArray_Descr *dtype, PyTypeObject *ptype)#

等价于 ndarray.view (self, dtype). 返回数组 self 的新视图,可能具有不同的数据类型 dtype 和不同的数组子类 ptype.

如果 dtype 为 NULL ,则返回的数组将具有与 self 相同的数据类型. 新的数据类型必须与 self 的大小一致. 要么 itemsize 必须相同,要么 self 必须是单段的且总字节数必须相同. 在后一种情况下,返回的数组的维度将在最后一个(或者对于 Fortran 风格的连续数组,则在第一个)维度中改变. 返回的数组和 self 的数据区域完全相同.

形状操作#

PyObject *PyArray_Newshape(PyArrayObject *self, PyArray_Dims *newshape, NPY_ORDER order)#

结果将是一个新数组(如果可能,指向与 self 相同的内存位置),但具有由 newshape 给定的形状. 如果新形状与 self 的步幅不兼容,则将返回具有新指定形状的数组的副本.

PyObject *PyArray_Reshape(PyArrayObject *self, PyObject *shape)#

等价于 ndarray.reshape (self, shape) ,其中 shape 是一个序列. 将 shape 转换为 PyArray_Dims 结构,并在内部调用 PyArray_Newshape . 为了向后兼容 – 不推荐

PyObject *PyArray_Squeeze(PyArrayObject *self)#

等价于 ndarray.squeeze (self). 返回 self 的一个新视图,其中所有长度为 1 的维度都从形状中移除.

警告

matrix 对象始终是 2 维的. 因此, PyArray_Squeeze 对 matrix 子类的数组没有影响.

PyObject *PyArray_SwapAxes(PyArrayObject *self, int a1, int a2)#

等价于 ndarray.swapaxes (self, a1, a2). 返回的数组是 self 中数据的一个新视图,其中给定的轴 a1 和 a2 被交换.

PyObject *PyArray_Resize(PyArrayObject *self, PyArray_Dims *newshape, int refcheck, NPY_ORDER fortran)#

等价于 ndarray.resize (self, newshape, refcheck = refcheck, order= fortran ). 此函数仅适用于单段数组. 它就地更改 self 的形状,如果 newshape 具有与旧形状不同的元素总数,则将重新分配 self 的内存. 如果需要重新分配,则 self 必须拥有其数据,具有 self - >base==NULL ,具有 self - >weakrefs==NULL ,并且(除非 refcheck 为 0)不被任何其他数组引用. fortran 参数可以是 NPY_ANYORDER , NPY_CORDERNPY_FORTRANORDER . 它目前没有效果. 最终,它可以用于确定在构造不同维度的数组时,resize 操作应如何查看数据. 成功时返回 None,出错时返回 NULL.

PyObject *PyArray_Transpose(PyArrayObject *self, PyArray_Dims *permute)#

等价于 ndarray.transpose (self, permute). 根据数据结构 permute 排列 ndarray 对象 self 的轴,并返回结果. 如果 permute 为 NULL ,则生成的数组的轴将反转. 例如,如果 self 的形状为 \(10\times20\times30\) ,并且 permute .ptr 为 (0,2,1),则结果的形状为 \(10\times30\times20.\) 如果 permute 为 NULL ,则结果的形状为 \(30\times20\times10.\)

PyObject *PyArray_Flatten(PyArrayObject *self, NPY_ORDER order)#

等价于 ndarray.flatten (self, order). 返回数组的一个 1-d 副本. 如果 order 是 NPY_FORTRANORDER ,则元素按 Fortran 顺序扫描出来(第一维变化最快). 如果 order 是 NPY_CORDER ,则 self 的元素按 C 顺序扫描(最后一维变化最快). 如果 order 是 NPY_ANYORDER ,那么 PyArray_ISFORTRAN (self) 的结果会被用来决定用哪个顺序来展平.

PyObject *PyArray_Ravel(PyArrayObject *self, NPY_ORDER order)#

等价于 self.ravel(order). 与 PyArray_Flatten (self, order) 具有相同的基础功能,但如果 order 为 0 并且 self 是 C 风格连续的,则形状会改变,但不会执行复制.

条目选择和操作#

PyObject *PyArray_TakeFrom(PyArrayObject *self, PyObject *indices, int axis, PyArrayObject *ret, NPY_CLIPMODE clipmode)#

等价于 ndarray.take (self, indices, axis, ret, clipmode),区别在于 Python 中的 axis =None 通过在 C 中设置 axis = NPY_MAXDIMS 来获得. 从 self 中提取由给定轴上整数值索引指示的项目. clipmode 参数可以是 NPY_RAISE , NPY_WRAPNPY_CLIP ,以指示如何处理越界索引. ret 参数可以指定一个输出数组,而不是在内部创建一个.

PyObject *PyArray_PutTo(PyArrayObject *self, PyObject *values, PyObject *indices, NPY_CLIPMODE clipmode)#

等价于 self.put(values, indices, clipmode ). 将值放入 self 中对应的(扁平化)索引处. 如果 values 太小,它将根据需要重复.

PyObject *PyArray_PutMask(PyArrayObject *self, PyObject *values, PyObject *mask)#

将 values 放置在 self 中 mask 中相应位置(使用展平的上下文)为真的地方. mask 和 self 数组必须具有相同的元素总数. 如果 values 太小,它将根据需要重复.

PyObject *PyArray_Repeat(PyArrayObject *self, PyObject *op, int axis)#

等价于 ndarray.repeat (self, op, axis). 沿着给定的轴复制 self 的元素,op 次. op 要么是一个标量整数,要么是长度为 self ->dimensions[ axis ] 的序列,指示沿轴重复每个项目的次数.

PyObject *PyArray_Choose(PyArrayObject *self, PyObject *op, PyArrayObject *ret, NPY_CLIPMODE clipmode)#

等价于 ndarray.choose (self, op, ret, clipmode). 通过基于 self 中的整数值从 op 中的数组序列中选择元素来创建一个新数组. 这些数组必须都可以广播到相同的形状,并且 self 中的条目应介于 0 和 len(op) 之间. 输出放置在 ret 中,除非它是 NULL ,在这种情况下会创建一个新的输出. clipmode 参数确定 self 中的条目不在 0 和 len(op) 之间时的行为.

NPY_RAISE#

引发 ValueError 异常;

NPY_WRAP#

通过添加 len(op) 来包装 values < 0,并通过减去 len(op) 来包装 values >=len(op),直到它们在范围内;

NPY_CLIP#

所有值都被裁剪到区域 [0, len(op) ).

PyObject *PyArray_Sort(PyArrayObject *self, int axis, NPY_SORTKIND kind)#

等价于 ndarray.sort (self, axis, kind). 返回一个数组,其中 self 的项目沿轴排序. 该数组使用由 kind 表示的算法进行排序,kind 是一个指向所用排序算法类型的整数/枚举.

PyObject *PyArray_ArgSort(PyArrayObject *self, int axis)#

等价于 ndarray.argsort (self, axis). 返回一个索引数组,这样沿着给定 axis 选择这些索引将返回 self 的排序版本. 如果 self ->descr 是一个定义了字段的数据类型,那么 self->descr->names 用于确定排序顺序. 第一个字段相等的比较将使用第二个字段,依此类推. 要更改结构化数组的排序顺序,请创建一个具有不同名称顺序的新数据类型,并使用该新数据类型构造数组的视图.

PyObject *PyArray_LexSort(PyObject *sort_keys, int axis)#

给定一个形状相同的数组序列(sort_keys),返回一个索引数组(类似于 PyArray_ArgSort (…)),该数组将按字典顺序对数组进行排序. 字典排序指定当发现两个键相等时,顺序基于后续键的比较. 需要为这些类型定义归并排序(使相等的条目保持不变). 通过首先使用第一个 sort_key 对索引进行排序,然后使用第二个 sort_key 等等来完成排序. 这等效于 lexsort(sort_keys, axis) Python 命令. 由于归并排序的工作方式,请务必理解 sort_keys 必须采用的顺序(与比较两个元素时使用的顺序相反).

如果这些数组都收集在一个结构化数组中,那么 PyArray_Sort (…) 也可以直接用于对数组进行排序.

PyObject *PyArray_SearchSorted(PyArrayObject *self, PyObject *values, NPY_SEARCHSIDE side, PyObject *perm)#

等价于 ndarray.searchsorted (self, values, side, perm).假设 self 是一个一维升序数组,那么输出就是一个与 values 形状相同的索引数组,使得如果 values 中的元素被插入到这些索引之前,self 的顺序将被保留.不会检查 self 是否为升序.

side 参数指示返回的索引应该是第一个合适位置的索引(如果为 NPY_SEARCHLEFT )还是最后一个(如果为 NPY_SEARCHRIGHT ).

sorter 参数,如果不是 NULL ,必须是一个与 self 长度相同的整数索引的 1D 数组,它将 self 排序为升序.这通常是对 PyArray_ArgSort (…) 的调用结果.使用二分搜索来查找所需的插入点.

int PyArray_Partition(PyArrayObject *self, PyArrayObject *ktharray, int axis, NPY_SELECTKIND which)#

等价于 ndarray.partition (self, ktharray, axis, kind).对数组进行分区,使得 ktharray 索引的元素的值位于数组完全排序后它们应该在的位置,并将所有小于第 k 个元素的元素放在前面,所有等于或大于第 k 个元素的元素放在后面.分区内所有元素的排序未定义.如果 self->descr 是一个定义了字段的数据类型,那么 self->descr->names 用于确定排序顺序.第一个字段相等的比较将使用第二个字段,依此类推.要更改结构化数组的排序顺序,请创建一个具有不同名称顺序的新数据类型,并使用该新数据类型构造数组的视图.成功时返回零,失败时返回 -1.

PyObject *PyArray_ArgPartition(PyArrayObject *op, PyArrayObject *ktharray, int axis, NPY_SELECTKIND which)#

等价于 ndarray.argpartition (self, ktharray, axis, kind).返回一个索引数组,使得沿着给定的 axis 选择这些索引将返回 self 的分区版本.

PyObject *PyArray_Diagonal(PyArrayObject *self, int offset, int axis1, int axis2)#

等价于 ndarray.diagonal (self, offset, axis1, axis2 ).返回由 axis1 和 axis2 定义的二维数组的偏移对角线.

npy_intp PyArray_CountNonzero(PyArrayObject *self)#

计算数组对象 self 中非零元素的数量.

PyObject *PyArray_Nonzero(PyArrayObject *self)#

等价于 ndarray.nonzero (self).返回一个索引数组的元组,用于选择 self 中非零的元素.如果 (nd= PyArray_NDIM ( self ))==1,则返回单个索引数组.索引数组的数据类型为 NPY_INTP .如果返回一个元组 (nd \(\neq\) 1),那么它的长度为 nd.

PyObject *PyArray_Compress(PyArrayObject *self, PyObject *condition, int axis, PyArrayObject *out)#

等价于 ndarray.compress (self, condition, axis ).返回沿轴 axis 对应于 condition 中为 true 的元素的元素.

计算#

小技巧

传入 NPY_RAVEL_AXIS 作为 axis,以达到与在 Python 中传入 axis=None 相同的效果(将数组视为一维数组).

备注

out 参数指定结果的放置位置.如果 out 为 NULL,则创建输出数组,否则输出放置在 out 中,out 必须是正确的大小和类型.即使 out 不为 NULL,也始终返回对输出数组的新引用.例程的调用者有责任 Py_DECREF out (如果 out 不为 NULL),否则会发生内存泄漏.

PyObject *PyArray_ArgMax(PyArrayObject *self, int axis, PyArrayObject *out)#

等价于 ndarray.argmax (self, axis).返回 self 沿轴 axis 的最大元素的索引.

PyObject *PyArray_ArgMin(PyArrayObject *self, int axis, PyArrayObject *out)#

等价于 ndarray.argmin (self, axis).返回 self 沿轴 axis 的最小元素的索引.

PyObject *PyArray_Max(PyArrayObject *self, int axis, PyArrayObject *out)#

等价于 ndarray.max (self, axis).返回 self 沿给定轴的最大元素.当结果是单个元素时,返回 numpy 标量而不是 ndarray.

PyObject *PyArray_Min(PyArrayObject *self, int axis, PyArrayObject *out)#

等价于 ndarray.min (self, axis).返回 self 沿给定轴的最小元素.当结果是单个元素时,返回 numpy 标量而不是 ndarray.

PyObject *PyArray_Ptp(PyArrayObject *self, int axis, PyArrayObject *out)#

返回 self 沿轴 axis 的最大元素和最小元素之间的差值.当结果是单个元素时,返回 numpy 标量而不是 ndarray.

备注

rtype参数指定了进行归约的数据类型.如果数组的数据类型不够"大"以处理输出,这一点很重要.默认情况下,对于"add"和"multiply" ufuncs(它们构成了mean,sum,cumsum,prod和cumprod函数的基础),所有整数数据类型都至少与 NPY_LONG 一样大.

PyObject *PyArray_Mean(PyArrayObject *self, int axis, int rtype, PyArrayObject *out)#

等效于 ndarray.mean (self, axis, rtype).返回沿给定轴的元素的平均值,使用枚举类型rtype作为求和的数据类型.使用 NPY_NOTYPE 作为rtype获得默认求和行为.

PyObject *PyArray_Trace(PyArrayObject *self, int offset, int axis1, int axis2, int rtype, PyArrayObject *out)#

等效于 ndarray.trace (self, offset, axis1, axis2, rtype).返回由 axis1 和 axis2 变量定义的二维数组的偏移对角线元素的总和(使用 rtype 作为求和的数据类型).正偏移选择主对角线上方的对角线.负偏移选择主对角线下方的对角线.

PyObject *PyArray_Clip(PyArrayObject *self, PyObject *min, PyObject *max)#

等效于 ndarray.clip (self, min, max).裁剪数组 self,使大于 max 的值固定为 max,小于 min 的值固定为 min.

PyObject *PyArray_Conjugate(PyArrayObject *self, PyArrayObject *out)#

等效于 ndarray.conjugate (self).返回 self 的复共轭.如果 self 不是复数数据类型,则返回带有引用的 self.

参数:
  • self – 输入数组.

  • out – 输出数组.如果提供,则结果将放入此数组.

返回:

self 的复共轭.

PyObject *PyArray_Round(PyArrayObject *self, int decimals, PyArrayObject *out)#

等效于 ndarray.round (self, decimals, out).返回元素四舍五入到最接近小数位的数组.小数位定义为 \(10^{-\textrm{decimals}}\) 位,因此负小数位会导致四舍五入到最接近的 10,100 等.如果 out 为 NULL ,则创建输出数组,否则输出放置在 out 中,out 必须是正确的大小和类型.

PyObject *PyArray_Std(PyArrayObject *self, int axis, int rtype, PyArrayObject *out)#

等效于 ndarray.std (self, axis, rtype).返回使用沿轴axis转换到数据类型rtype的数据的标准差.

PyObject *PyArray_Sum(PyArrayObject *self, int axis, int rtype, PyArrayObject *out)#

等效于 ndarray.sum (self, axis, rtype).返回 self 中沿轴 axis 的元素的一维向量和.将数据转换为数据类型 rtype 后执行求和.

PyObject *PyArray_CumSum(PyArrayObject *self, int axis, int rtype, PyArrayObject *out)#

等效于 ndarray.cumsum (self, axis, rtype).返回 self 中沿轴 axis 的元素的累积一维和.将数据转换为数据类型 rtype 后执行求和.

PyObject *PyArray_Prod(PyArrayObject *self, int axis, int rtype, PyArrayObject *out)#

等效于 ndarray.prod (self, axis, rtype).返回 self 中沿轴 axis 的元素的一维积.将数据转换为数据类型 rtype 后执行乘积.

PyObject *PyArray_CumProd(PyArrayObject *self, int axis, int rtype, PyArrayObject *out)#

等效于 ndarray.cumprod (self, axis, rtype).返回 self 中沿 axis 的元素的累积一维积.将数据转换为数据类型 rtype 后执行乘积.

PyObject *PyArray_All(PyArrayObject *self, int axis, PyArrayObject *out)#

等效于 ndarray.all (self, axis).对于 self 的由 axis 定义的每个所有元素均为 True 的一维子数组,返回一个具有 True 元素的数组.

PyObject *PyArray_Any(PyArrayObject *self, int axis, PyArrayObject *out)#

等效于 ndarray.any (self, axis).对于 self 的由 axis 定义的每个任何元素为 True 的一维子数组,返回一个具有 True 元素的数组.

函数#

数组函数#

int PyArray_AsCArray(PyObject **op, void *ptr, npy_intp *dims, int nd, PyArray_Descr *typedescr)#

有时,将多维数组作为 C 风格的多维数组访问很有用,这样就可以使用 C 的 a[i][j][k] 语法来实现算法.此例程返回一个指针 ptr,该指针模拟了这种 C 风格的数组,适用于 1-,2- 和 3-d ndarray.

参数:
  • op – 任何 Python 对象的地址.此 Python 对象将被替换为等效的,行为良好的,C 风格的连续 ndarray,其数据类型由最后两个参数指定.请确保以这种方式窃取对输入对象的引用是合理的.

  • ptr – (对于 1-d,对于 2-d 或对于 3-d)变量的地址,其中 ctype 是数据类型的等效 C 类型.返回时,ptr 将可以作为 1-d,2-d 或 3-d 数组来寻址.

  • dims – 一个输出数组,其中包含数组对象的形状.此数组给出了将要发生的任何循环的边界.

  • nd – 数组的维度(1,2 或 3).

  • typedescr – 一个 PyArray_Descr 结构,指示所需的数据类型(包括所需的字节顺序).调用将窃取对该参数的引用.

备注

对于二维和三维数组,C 风格数组的模拟并不完整.例如,模拟的指针数组不能传递给期望特定的,静态定义的二维和三维数组的子程序.要传递给需要这些输入的函数,您必须静态定义所需的数组并复制数据.

int PyArray_Free(PyObject *op, void *ptr)#

必须使用从 PyArray_AsCArray (…) 返回的相同对象和内存位置调用.此函数清理否则会被泄露的内存.

PyObject *PyArray_Concatenate(PyObject *obj, int axis)#

将 obj 中的对象序列沿 axis 连接成一个数组.如果维度或类型不兼容,则会引发错误.

PyObject *PyArray_InnerProduct(PyObject *obj1, PyObject *obj2)#

计算 obj1 和 obj2 的最后一个维度上的乘积和.两个数组均未共轭.

PyObject *PyArray_MatrixProduct(PyObject *obj1, PyObject *obj)#

计算 obj1 的最后一个维度和 obj2 的倒数第二个维度上的乘积和.对于二维数组,这是一个矩阵积.两个数组均未共轭.

PyObject *PyArray_MatrixProduct2(PyObject *obj1, PyObject *obj, PyArrayObject *out)#

与 PyArray_MatrixProduct 相同,但将结果存储在 out 中.输出数组必须具有正确的形状,类型并且是 C-contiguous,否则会引发异常.

PyArrayObject *PyArray_EinsteinSum(char *subscripts, npy_intp nop, PyArrayObject **op_in, PyArray_Descr *dtype, NPY_ORDER order, NPY_CASTING casting, PyArrayObject *out)#

将爱因斯坦求和约定应用于提供的数组操作数,返回一个新数组或将结果放置在 out 中.subscripts 中的字符串是以逗号分隔的索引字母列表.操作数的数量在 nop 中,而 op_in 是一个包含这些操作数的数组.输出的数据类型可以用 dtype 强制,输出顺序可以用 order 强制(推荐使用 NPY_KEEPORDER ),并且当指定 dtype 时,casting 指示数据转换应该有多宽松.

有关更多详细信息,请参见 einsum 函数.

PyObject *PyArray_Correlate(PyObject *op1, PyObject *op2, int mode)#

计算一维数组 op1 和 op2 的一维相关性.通过将 op1 乘以 op2 的移位版本并对结果求和,在每个输出点计算相关性.由于移位,op1 和 op2 定义范围之外的所需值被解释为零.模式确定要返回的移位数量:0 - 仅返回不需要假定零值的移位;1 - 返回一个与 op1 大小相同的对象;2 - 返回所有可能的移位(接受任何重叠).

注释

这不会计算通常的相关性:如果 op2 大于 op1,则交换参数,并且永远不会对复数数组进行共轭.有关通常的信号处理相关性,请参见 PyArray_Correlate2.

PyObject *PyArray_Correlate2(PyObject *op1, PyObject *op2, int mode)#

PyArray_Correlate 的更新版本,它对一维数组使用相关的常用定义.通过将 op1 乘以 op2 的移位版本并对结果求和,在每个输出点计算相关性.由于移位,op1 和 op2 定义范围之外的所需值被解释为零.模式确定要返回的移位数量:0 - 仅返回不需要假定零值的移位;1 - 返回一个与 op1 大小相同的对象;2 - 返回所有可能的移位(接受任何重叠).

注释

按如下方式计算 z:

z[k] = sum_n op1[n] * conj(op2[n+k])
PyObject *PyArray_Where(PyObject *condition, PyObject *x, PyObject *y)#

如果 xy 均为 NULL ,则返回 PyArray_Nonzero (condition).否则,必须给出 x 和 y,并且返回的对象的形状与 condition 类似,并且具有 x 和 y 的元素,其中 condition 分别为 True 或 False.

其他函数#

npy_bool PyArray_CheckStrides(int elsize, int nd, npy_intp numbytes, npy_intp const *dims, npy_intp const *newstrides)#

确定 newstrides 是否是与形状为 dims 且元素大小为 elsize 的 nd 维数组的内存一致的 strides 数组.检查 newstrides 数组,以查看在每个方向上跳过提供的字节数是否意味着跳过超过 numbytes,numbytes 是可用内存段的假定大小.如果 numbytes 为 0,则计算一个等效的 numbytes,假设 nd,dims 和 elsize 指的是单段数组.如果 newstrides 可接受,则返回 NPY_TRUE ,否则返回 NPY_FALSE .

npy_intp PyArray_MultiplyList(npy_intp const *seq, int n)#
int PyArray_MultiplyIntList(int const *seq, int n)#

这两个例程都将 n 长度的整数数组 seq 相乘并返回结果.不执行溢出检查.

int PyArray_CompareLists(npy_intp const *l1, npy_intp const *l2, int n)#

给定两个 n 长度的整数数组 l1 和 l2,如果列表相同则返回 1;否则,返回 0.

带有对象语义的辅助数据#

type NpyAuxData#

当处理由其他 dtype 组成的更复杂的数据类型(如 struct dtype)时,创建操作数据类型的内部循环需要携带附加数据.NumPy 通过 struct NpyAuxData 支持这个概念,并强制执行一些约定,以便能够做到这一点.

定义 NpyAuxData 类似于在 C++ 中定义一个类,但对象语义必须手动跟踪,因为 API 在 C 中.这是一个使用元素复制器函数作为原语来加倍元素的函数的示例.

typedef struct {
    NpyAuxData base;
    ElementCopier_Func *func;
    NpyAuxData *funcdata;
} eldoubler_aux_data;

void free_element_doubler_aux_data(NpyAuxData *data)
{
    eldoubler_aux_data *d = (eldoubler_aux_data *)data;
    /* Free the memory owned by this auxdata */
    NPY_AUXDATA_FREE(d->funcdata);
    PyArray_free(d);
}

NpyAuxData *clone_element_doubler_aux_data(NpyAuxData *data)
{
    eldoubler_aux_data *ret = PyArray_malloc(sizeof(eldoubler_aux_data));
    if (ret == NULL) {
        return NULL;
    }

    /* Raw copy of all data */
    memcpy(ret, data, sizeof(eldoubler_aux_data));

    /* Fix up the owned auxdata so we have our own copy */
    ret->funcdata = NPY_AUXDATA_CLONE(ret->funcdata);
    if (ret->funcdata == NULL) {
        PyArray_free(ret);
        return NULL;
    }

    return (NpyAuxData *)ret;
}

NpyAuxData *create_element_doubler_aux_data(
                            ElementCopier_Func *func,
                            NpyAuxData *funcdata)
{
    eldoubler_aux_data *ret = PyArray_malloc(sizeof(eldoubler_aux_data));
    if (ret == NULL) {
        PyErr_NoMemory();
        return NULL;
    }
    memset(&ret, 0, sizeof(eldoubler_aux_data));
    ret->base->free = &free_element_doubler_aux_data;
    ret->base->clone = &clone_element_doubler_aux_data;
    ret->func = func;
    ret->funcdata = funcdata;

    return (NpyAuxData *)ret;
}
type NpyAuxData_FreeFunc#

NpyAuxData 释放函数的函数指针类型.

type NpyAuxData_CloneFunc#

NpyAuxData 克隆函数的函数指针类型.这些函数永远不应该在出错时设置 Python 异常,因为它们可能从多线程上下文中调用.

void NPY_AUXDATA_FREE(NpyAuxData *auxdata)#

一个宏,它适当地调用 auxdata 的释放函数,如果 auxdata 为 NULL,则不执行任何操作.

NpyAuxData *NPY_AUXDATA_CLONE(NpyAuxData *auxdata)#

一个宏,它适当地调用 auxdata 的克隆函数,返回辅助数据的深拷贝.

数组迭代器#

从 NumPy 1.6.0 开始,这些数组迭代器已被新的数组迭代器 NpyIter 取代.

数组迭代器是一种快速有效地访问 N 维数组元素的方法,如 the example 所示,它提供了对这种从 C 循环遍历数组的有用方法的更多描述.

PyObject *PyArray_IterNew(PyObject *arr)#

从数组 arr 返回一个数组迭代器对象.这等同于 arr. flat.数组迭代器对象可以很容易地以 C 风格的连续方式循环遍历 N 维非连续数组.

PyObject *PyArray_IterAllButAxis(PyObject *arr, int *axis)#

返回一个数组迭代器,它将迭代除 axis 中提供的轴之外的所有轴.返回的迭代器不能与 PyArray_ITER_GOTO1D 一起使用.这个迭代器可以用来编写类似于 ufunc 所做的事情,其中最大轴的循环是由一个单独的子例程完成的.如果 axis 为负,则 axis 将设置为具有最小步幅的轴,并将使用该轴.

PyObject *PyArray_BroadcastToShape(PyObject *arr, npy_intp const *dimensions, int nd)#

返回一个数组迭代器,该迭代器广播为以 dimensions 和 nd 提供的形状的数组进行迭代.

int PyArrayIter_Check(PyObject *op)#

如果 op 是一个数组迭代器(或者数组迭代器类型的子类的实例),则返回 true.

void PyArray_ITER_RESET(PyObject *iterator)#

将迭代器重置到数组的开头.

void PyArray_ITER_NEXT(PyObject *iterator)#

递增迭代器的 index 和 dataptr 成员,使其指向数组的下一个元素.如果数组不是 (C 风格) 连续的,则还要递增 N 维坐标数组.

void *PyArray_ITER_DATA(PyObject *iterator)#

指向数组当前元素的指针.

void PyArray_ITER_GOTO(PyObject *iterator, npy_intp *destination)#

将迭代器的 index,dataptr 和坐标成员设置为数组中由 N 维 c 数组 destination 指示的位置,destination 的大小必须至少为 iterator ->nd_m1+1.

void PyArray_ITER_GOTO1D(PyObject *iterator, npy_intp index)#

将迭代器的 index 和 dataptr 设置为数组中由整数索引指示的位置,该索引指向 C 风格扁平化数组中的一个元素.

int PyArray_ITER_NOTDONE(PyObject *iterator)#

只要迭代器没有循环遍历所有元素,则评估为 TRUE,否则评估为 FALSE.

广播 (多重迭代器)#

PyObject *PyArray_MultiIterNew(int num, ...)#

一个简化的广播接口.此函数接受要广播的数组的数量,然后是 num 个额外的 ( PyObject * ) 参数.这些参数被转换为数组并创建迭代器.然后对生成的多重迭代器对象调用 PyArray_Broadcast .然后返回生成的广播多重迭代器对象.然后可以使用一个循环并使用 PyArray_MultiIter_NEXT 来执行广播操作 (..)

void PyArray_MultiIter_RESET(PyObject *multi)#

将所有迭代器重置为多重迭代器对象 multi 中的开头.

void PyArray_MultiIter_NEXT(PyObject *multi)#

将多重迭代器对象 multi 中的每个迭代器推进到它的下一个(广播的)元素.

void *PyArray_MultiIter_DATA(PyObject *multi, int i)#

返回多重迭代器对象中第 i \(^{\textrm{th}}\) 个迭代器的数据指针.

void PyArray_MultiIter_NEXTi(PyObject *multi, int i)#

仅推进第 i \(^{\textrm{th}}\) 个迭代器的指针.

void PyArray_MultiIter_GOTO(PyObject *multi, npy_intp *destination)#

将多重迭代器对象 multi 中的每个迭代器推进到给定的 \(N\) 维目的地,其中 \(N\) 是广播数组中的维数.

void PyArray_MultiIter_GOTO1D(PyObject *multi, npy_intp index)#

将多重迭代器对象 multi 中的每个迭代器推进到扁平化广播数组中索引的相应位置.

int PyArray_MultiIter_NOTDONE(PyObject *multi)#

只要多重迭代器还没有循环遍历完所有的元素(广播结果的元素),则计算结果为 TRUE,否则计算结果为 FALSE.

npy_intp PyArray_MultiIter_SIZE(PyArrayMultiIterObject *multi)#

在 1.26.0 版本加入.

返回多重迭代器对象的总广播大小.

int PyArray_MultiIter_NDIM(PyArrayMultiIterObject *multi)#

在 1.26.0 版本加入.

返回多重迭代器对象的广播结果中的维度数.

npy_intp PyArray_MultiIter_INDEX(PyArrayMultiIterObject *multi)#

在 1.26.0 版本加入.

返回多重迭代器对象广播结果中当前的(1-d)索引.

int PyArray_MultiIter_NUMITER(PyArrayMultiIterObject *multi)#

在 1.26.0 版本加入.

返回由多重迭代器对象表示的迭代器数量.

void **PyArray_MultiIter_ITERS(PyArrayMultiIterObject *multi)#

在 1.26.0 版本加入.

返回一个迭代器对象数组,该数组包含用于一起广播的数组的迭代器. 返回时,迭代器会针对广播进行调整.

npy_intp *PyArray_MultiIter_DIMS(PyArrayMultiIterObject *multi)#

在 1.26.0 版本加入.

返回指向多重迭代器对象广播结果的维度/形状的指针.

int PyArray_Broadcast(PyArrayMultiIterObject *mit)#

此函数封装了广播规则. mit 容器应已包含所有需要广播的数组的迭代器. 返回时,将调整这些迭代器,以便同时迭代每个迭代器将完成广播. 如果发生错误,则返回一个负数.

int PyArray_RemoveSmallest(PyArrayMultiIterObject *mit)#

此函数接受一个先前已"广播"的多重迭代器对象,找到广播结果中"步幅总和"最小的维度,并调整所有迭代器,以便不对该维度进行迭代(通过有效地使它们在该维度上的长度为 1). 除非 mit ->nd 为 0,否则返回相应的维度,此时返回 -1. 此函数对于构造类似 ufunc 的例程非常有用,这些例程可以正确广播其输入,然后将例程的跨步 1-d 版本作为内部循环调用. 这个 1-d 版本通常针对速度进行了优化,因此循环应该在不需要大步幅跳跃的轴上执行.

邻域迭代器#

邻域迭代器是迭代器对象的子类,可用于迭代点的邻域. 例如,您可能想要迭代 3d 图像的每个体素,并且对于每个这样的体素,迭代一个超立方体. 邻域迭代器自动处理边界,因此使得这种代码比手动边界处理更容易编写,但会略微增加开销.

PyObject *PyArray_NeighborhoodIterNew(PyArrayIterObject *iter, npy_intp bounds, int mode, PyArrayObject *fill_value)#

此函数从现有迭代器创建一个新的邻域迭代器. 邻域将相对于 iter 当前指向的位置进行计算,bounds 定义邻域迭代器的形状,mode 参数定义边界处理模式.

bounds 参数应为 (2 * iter->ao->nd) 数组,例如范围 bound[2i]->bounds[2i+1] 定义了维度 i 的行走范围(两个边界都包含在行走的坐标中). 边界应针对每个维度进行排序 (bounds[2i] <= bounds[2i+1]).

mode 应为以下之一:

NPY_NEIGHBORHOOD_ITER_ZERO_PADDING#

零填充. 边界外的值将为 0.

NPY_NEIGHBORHOOD_ITER_ONE_PADDING#

一填充. 边界外的值将为 1.

NPY_NEIGHBORHOOD_ITER_CONSTANT_PADDING#

常量填充. 边界外的值将与 fill_value 中的第一个项目相同.

NPY_NEIGHBORHOOD_ITER_MIRROR_PADDING#

镜像填充. 边界外的值将像数组项被镜像一样. 例如,对于数组 [1, 2, 3, 4],x[-2] 将为 2,x[-2] 将为 1,x[4] 将为 4,x[5] 将为 1,等等…

NPY_NEIGHBORHOOD_ITER_CIRCULAR_PADDING#

循环填充. 边界外的值将如同数组被重复一样. 例如,对于数组 [1, 2, 3, 4],x[-2] 将为 3,x[-2] 将为 4,x[4] 将为 1,x[5] 将为 2,等等…

如果模式是常量填充( NPY_NEIGHBORHOOD_ITER_CONSTANT_PADDING ),则 fill_value 应指向一个数组对象,该对象保存填充值(如果数组包含多个项目,则第一个项目将是填充值). 对于其他情况,fill_value 可能为 NULL.

  • 迭代器保存对 iter 的引用

  • 失败时返回 NULL(在这种情况下,iter 的引用计数不会更改)

  • iter 本身可以是 Neighborhood 迭代器:这对于例如自动边界处理非常有用

  • 由此函数返回的对象应可以安全地用作普通迭代器

  • 如果 iter 的位置发生更改,则任何后续的 PyArrayNeighborhoodIter_Next 调用都是未定义的行为,并且必须调用 PyArrayNeighborhoodIter_Reset.

  • 如果 iter 的位置不是数据的开头,并且 iter 的底层数据是连续的,则迭代器将指向数据的开头,而不是 iter 指向的位置. 为避免这种情况,应仅在创建迭代器后才将 iter 移动到所需位置,并且必须调用 PyArrayNeighborhoodIter_Reset.

PyArrayIterObject *iter;
PyArrayNeighborhoodIterObject *neigh_iter;
iter = PyArray_IterNew(x);

/*For a 3x3 kernel */
bounds = {-1, 1, -1, 1};
neigh_iter = (PyArrayNeighborhoodIterObject*)PyArray_NeighborhoodIterNew(
     iter, bounds, NPY_NEIGHBORHOOD_ITER_ZERO_PADDING, NULL);

for(i = 0; i < iter->size; ++i) {
     for (j = 0; j < neigh_iter->size; ++j) {
             /* Walk around the item currently pointed by iter->dataptr */
             PyArrayNeighborhoodIter_Next(neigh_iter);
     }

     /* Move to the next point of iter */
     PyArrayIter_Next(iter);
     PyArrayNeighborhoodIter_Reset(neigh_iter);
}
int PyArrayNeighborhoodIter_Reset(PyArrayNeighborhoodIterObject *iter)#

将迭代器位置重置为邻域的第一个点.每当在 PyArray_NeighborhoodIterObject 处给出的 iter 参数发生更改时,都应调用此函数(参见示例)

int PyArrayNeighborhoodIter_Next(PyArrayNeighborhoodIterObject *iter)#

在此调用之后,iter->dataptr 指向邻域的下一点.在访问完邻域的每个点之后调用此函数是未定义的.

数组标量#

PyObject *PyArray_Return(PyArrayObject *arr)#

此函数会窃取对 arr 的引用.

此函数检查 arr 是否为 0 维数组,如果是,则返回相应的数组标量.每当可能将 0 维数组返回给 Python 时,都应使用此函数.

PyObject *PyArray_Scalar(void *data, PyArray_Descr *dtype, PyObject *base)#

通过从 data 指向的内存复制,返回给定 dtype 的数组标量对象.base 应该是 data 的所有者数组对象.如果 dtypevoid 标量,或者如果设置了 NPY_USE_GETITEM 标志并且已知 getitem 方法使用 arr 参数而不检查它是否为 NULL ,则需要 base.否则, base 可以为 NULL .

如果数据不是本机字节顺序(如 dtype->byteorder 所指示),则此函数将字节交换数据,因为数组标量始终处于正确的机器字节顺序.

PyObject *PyArray_ToScalar(void *data, PyArrayObject *arr)#

返回一个由数组对象 arr 指示的类型和 itemsize 的数组标量对象,该对象从 data 指向的内存复制,并且如果 arr 中的数据不是机器字节顺序,则进行交换.

PyObject *PyArray_FromScalar(PyObject *scalar, PyArray_Descr *outcode)#

从标量返回一个由 outcode 确定的类型的 0 维数组,该标量应该是数组标量对象.如果 outcode 为 NULL,则类型由标量确定.

void PyArray_ScalarAsCtype(PyObject *scalar, void *ctypeptr)#

在 ctypeptr 中返回一个指向数组标量中实际值的指针.没有错误检查,因此 scalar 必须是数组标量对象,并且 ctypeptr 必须有足够的空间来保存正确的类型.对于可变大小的类型,指向数据的指针被复制到 ctypeptr 的内存中,对于所有其他类型,实际数据被复制到 ctypeptr 指向的地址.

int PyArray_CastScalarToCtype(PyObject *scalar, void *ctypeptr, PyArray_Descr *outcode)#

将数组标量 scalar 中的数据(强制转换为 outcode 指示的数据类型)返回到 ctypeptr 指向的内存中(该内存必须足够大以处理传入的内存).

失败时返回 -1,成功时返回 0.

PyObject *PyArray_TypeObjectFromType(int type)#

从类型编号 type 返回标量类型对象.等效于 PyArray_DescrFromType (type)->typeobj,但引用计数和错误检查除外.成功时返回对 typeobject 的新引用,失败时返回 NULL .

NPY_SCALARKIND PyArray_ScalarKind(int typenum, PyArrayObject **arr)#

查询标量值的特殊提升的传统方法.NumPy 本身不再使用它,并且预计最终会被弃用.

新的 DType 可以定义特定于 Python 标量的提升规则.

int PyArray_CanCoerceScalar(char thistype, char neededtype, NPY_SCALARKIND scalar)#

查询标量值的特殊提升的传统方法.NumPy 本身不再使用它,并且预计最终会被弃用.

对于类似的目的,请使用 PyArray_ResultType .

数据类型描述符#

警告

数据类型对象必须进行引用计数,因此请注意不同 C-API 调用对数据类型引用的操作.标准规则是,当返回数据类型对象时,它是一个新引用.接受 PyArray_Descr* 对象并返回数组的函数会窃取对其输入的数据类型的引用,除非另有说明.因此,您必须拥有对用作此类函数输入的任何数据类型对象的引用.

int PyArray_DescrCheck(PyObject *obj)#

如果 obj 是数据类型对象 ( PyArray_Descr* ),则求值为 true.

PyArray_Descr *PyArray_DescrNew(PyArray_Descr *obj)#

从 obj 复制返回一个新的数据类型对象(字段引用只是更新,以便新对象指向相同的字段字典,如果有的话).

PyArray_Descr *PyArray_DescrNewFromType(int typenum)#

从由 typenum 指示的内置(或用户注册的)数据类型创建一个新的数据类型对象.所有内置类型都不应更改其任何字段.这将创建一个新的 PyArray_Descr 结构的副本,以便您可以根据需要填充它.对于需要具有新的 elsize 成员才能在数组构造中有意义的灵活数据类型,此函数尤为重要.

PyArray_Descr *PyArray_DescrNewByteorder(PyArray_Descr *obj, char newendian)#

创建一个新的数据类型对象,其字节顺序根据 newendian 设置.所有引用的数据类型对象(在数据类型对象的 subdescr 和 fields 成员中)也会被更改(递归).

newendian 的值是以下宏之一:

NPY_IGNORE#
NPY_SWAP#
NPY_NATIVE#
NPY_LITTLE#
NPY_BIG#

如果遇到 NPY_IGNORE 的字节顺序,则保持不变.如果 newendian 是 NPY_SWAP ,则所有字节顺序都会被交换.其他有效的 newendian 值是 NPY_NATIVE , NPY_LITTLENPY_BIG ,它们都会导致返回的数据类型描述符(及其所有引用的数据类型描述符)具有相应的字节顺序.

PyArray_Descr *PyArray_DescrFromObject(PyObject *op, PyArray_Descr *mintype)#

从对象 op(应该是一个"嵌套"序列对象)和最小数据类型描述符 mintype(可以为 NULL )中确定适当的数据类型对象.在行为上类似于 array(op).dtype.不要将此函数与 PyArray_DescrConverter 混淆.此函数主要查看(嵌套)序列中的所有对象,并从它找到的元素中确定数据类型.

PyArray_Descr *PyArray_DescrFromScalar(PyObject *scalar)#

从数组标量对象返回数据类型对象. 不会进行检查以确保 scalar 是数组标量. 如果无法确定合适的数据类型,则默认情况下返回 NPY_OBJECT 的数据类型.

PyArray_Descr *PyArray_DescrFromType(int typenum)#

返回与 typenum 对应的数据类型对象. typenum 可以是枚举类型之一,枚举类型之一的字符代码或用户定义的类型. 如果要使用可变大小的数组,则需要 flexible typenum 并将 results elsize 参数设置为所需的大小. typenum 是 NPY_TYPES 之一.

int PyArray_DescrConverter(PyObject *obj, PyArray_Descr **dtype)#

将任何兼容的 Python 对象 obj 转换为 dtype 中的数据类型对象. 大量的 Python 对象都可以转换为数据类型对象. 有关完整说明,请参见 数据类型对象 ( dtype ) . 此版本的转换器将 None 对象转换为 NPY_DEFAULT_TYPE 数据类型对象. 此函数可以与 PyArg_ParseTuple 处理中的 “O&” 字符代码一起使用.

int PyArray_DescrConverter2(PyObject *obj, PyArray_Descr **dtype)#

将任何兼容的 Python 对象 obj 转换为 dtype 中的数据类型对象. 此版本的转换器转换 None 对象,以便返回的数据类型为 NULL . 此函数也可以与 PyArg_ParseTuple 处理中的 “O&” 字符一起使用.

int PyArray_DescrAlignConverter(PyObject *obj, PyArray_Descr **dtype)#

类似于 PyArray_DescrConverter ,不同之处在于它将类似于 C 结构的 object 按照编译器的方式在字边界上对齐.

int PyArray_DescrAlignConverter2(PyObject *obj, PyArray_Descr **dtype)#

类似于 PyArray_DescrConverter2 ,不同之处在于它将类似于 C 结构的 object 按照编译器的方式在字边界上对齐.

数据类型提升和检查#

PyArray_DTypeMeta *PyArray_CommonDType(const PyArray_DTypeMeta *dtype1, const PyArray_DTypeMeta *dtype2)#

此函数定义了公共的 DType 运算符. 请注意,公共的 DType 不会是 object (除非其中一个 DType 是 object ). 类似于 numpy.result_type ,但适用于类而不是实例.

PyArray_DTypeMeta *PyArray_PromoteDTypeSequence(npy_intp length, PyArray_DTypeMeta **dtypes_in)#

以一种应该保证即使在更改顺序时也能获得稳定结果的方式来提升 DType 列表. 此函数更智能,并且通常可以在 common_dtype(common_dtype(dt1, dt2), dt3) 取决于操作顺序或失败时返回成功且明确的结果. 尽管如此,DType 应该旨在确保其公共数据类型实现是结合性和交换性的! (主要是,无符号和有符号整数不是.)

为了保证一致的结果,DType 必须"传递地"实现公共 DType. 如果 A 提升 B 并且 B 提升 C,那么 A 通常也必须提升 C; 其中"提升"是指实现提升. (对于抽象 DType,有一些例外)

通常,只要最通用的 dtype 严格更大或与所有其他 dtype 兼容,此方法总是有效. 例如,使用任何其他浮点数,整数或无符号整数提升 float16 再次给出浮点数Number.

PyArray_Descr *PyArray_GetDefaultDescr(const PyArray_DTypeMeta *DType)#

给定一个 DType 类,返回默认实例(描述符). 这首先检查 singleton ,仅在必要时才调用 default_descr 函数.

自定义数据类型#

在 2.0 版本加入.

这些函数允许在 NumPy 之外定义自定义的灵活数据类型. 有关新 DType 系统的基本原理和设计的更多详细信息,请参见 NEP 42 . 有关大量示例 DType,请参见 numpy-user-dtypes repository . 另请参见 PyArray_DTypeMeta 和 PyArrayDTypeMeta_Spec 以获取有关 PyArray_DTypeMetaPyArrayDTypeMeta_Spec 的文档.

int PyArrayInitDTypeMeta_FromSpec(PyArray_DTypeMeta *Dtype, PyArrayDTypeMeta_Spec *spec)#

初始化一个新的 DType. 它当前必须是一个静态 Python C 类型,声明为 PyArray_DTypeMeta 而不是 PyTypeObject . 此外,它必须子类化 np.dtype 并将其类型设置为 PyArrayDTypeMeta_Type (在调用 PyType_Ready 之前),与正常的 PyTypeObject 相比,它具有其他字段. 有关参数化和非参数化数据类型用法的示例,请参见 numpy-user-dtypes 存储库中的示例.

标志#

可以在 PyArrayDTypeMeta_Spec 上设置的标志,用于初始化 DType.

NPY_DT_ABSTRACT#

指示 DType 是 DType 层级结构中的一个抽象"基础" DType,不应直接实例化.

NPY_DT_PARAMETRIC#

指示 DType 是参数化的,并且没有唯一的单例实例.

NPY_DT_NUMERIC#

指示 DType 表示一个数值.

槽位 ID 和 API 函数类型定义#

这些 ID 对应于 DType API 中的槽位,用于从 PyArrayDTypeMeta_Spec 结构的 slots 数组成员中识别每个槽位的实现.

NPY_DT_discover_descr_from_pyobject#
typedef PyArray_Descr *(PyArrayDTypeMeta_DiscoverDescrFromPyobject)(PyArray_DTypeMeta *cls, PyObject *obj)#

用于 DType 推断,以找到给定 PyObject 的正确 DType.必须返回一个适合存储传入的 python 对象中的数据的描述符实例.obj 是要检查的 python 对象,cls 是要为其创建描述符的 DType 类.

NPY_DT_default_descr#
typedef PyArray_Descr *(PyArrayDTypeMeta_DefaultDescriptor)(PyArray_DTypeMeta *cls)#

返回 DType 的默认描述符实例.必须为参数化数据类型定义.非参数化数据类型默认返回单例.

NPY_DT_common_dtype#
typedef PyArray_DTypeMeta *(PyArrayDTypeMeta_CommonDType)(PyArray_DTypeMeta *dtype1, PyArray_DTypeMeta *dtype2)#

给定两个输入 DType,确定可以存储两种类型的值的适当"公共" DType.如果不存在这样的类型,则返回 Py_NotImplemented .

NPY_DT_common_instance#
typedef PyArray_Descr *(PyArrayDTypeMeta_CommonInstance)(PyArray_Descr *dtype1, PyArray_Descr *dtype2)#

给定两个输入描述符,确定可以存储两个实例的值的适当"公共"描述符.如果出错,则返回 NULL .

NPY_DT_ensure_canonical#
typedef PyArray_Descr *(PyArrayDTypeMeta_EnsureCanonical)(PyArray_Descr *dtype)#

返回描述符实例的"规范"表示.规范描述符的概念推广了字节顺序的概念,因为规范描述符始终具有本机字节顺序.如果描述符已经是规范的,则此函数返回对输入描述符的新引用.

NPY_DT_setitem#
typedef int (PyArrayDTypeMeta_SetItem)(PyArray_Descr*, PyObject*, char*)#

为给定 PyObject 的数组元素实现标量 setitem.

NPY_DT_getitem#
typedef PyObject *(PyArrayDTypeMeta_GetItem)(PyArray_Descr*, char*)#

为数组元素实现标量 getitem.必须返回一个 python 标量.

NPY_DT_get_clear_loop#

如果已定义,则设置一个遍历循环,清除数组中的数据.这对于必须在数组被垃圾回收之前清理数组条目的引用数组最有用.实现 PyArrayMethod_GetTraverseLoop .

NPY_DT_get_fill_zero_loop#

如果已定义,则设置一个遍历循环,用"零"值填充数组,这可能具有 DType 特定的含义.对于需要写入自定义 sentinel 值(表示零)的数组,如果在某种程度上零填充数组不足够,则会在 numpy.zeros 中调用此方法.实现 PyArrayMethod_GetTraverseLoop .

NPY_DT_finalize_descr#
typedef PyArray_Descr *(PyArrayDTypeMeta_FinalizeDescriptor)(PyArray_Descr *dtype)#

如果已定义,则在创建数组后调用该函数来"最终确定"描述符实例.此函数的一种用途是强制新创建的数组具有新创建的描述符实例,无论用户提供什么输入描述符.

PyArray_ArrFuncs 槽位#

除了上面的槽位外,还公开了以下槽位,以允许填充附加到描述符实例的 PyArray_ArrFuncs 结构. 请注意,将来这些将被正确的 DType API 槽位替换,但目前我们公开了传统的 PyArray_ArrFuncs 槽位.

NPY_DT_PyArray_ArrFuncs_getitem#

允许设置每个 dtype 的 getitem. 请注意,除非使用 NPY_DT_getitem ID 定义的函数调用的默认版本不合适,否则不需要定义此项. 此版本将比使用 NPY_DT_getitem 稍微快一些,但代价是有时需要处理 NULL 输入数组.

NPY_DT_PyArray_ArrFuncs_setitem#

允许设置每个 dtype 的 setitem. 请注意,除非由于某种原因使用 NPY_DT_setitem ID 定义的函数调用的默认版本不合适,否则不需要定义此项.

NPY_DT_PyArray_ArrFuncs_compare#

计算 numpy.sort 的比较,实现 PyArray_CompareFunc .

NPY_DT_PyArray_ArrFuncs_argmax#

计算 numpy.argmax 的 argmax,实现 PyArray_ArgFunc .

NPY_DT_PyArray_ArrFuncs_argmin#

计算 numpy.argmin 的 argmin,实现 PyArray_ArgFunc .

NPY_DT_PyArray_ArrFuncs_dotfunc#

计算 numpy.dot 的点积,实现 PyArray_DotFunc .

NPY_DT_PyArray_ArrFuncs_scanfunc#

numpy.fromfile 的格式化输入函数,实现 PyArray_ScanFunc .

NPY_DT_PyArray_ArrFuncs_fromstr#

numpy.fromstring 的字符串解析函数,实现 PyArray_FromStrFunc .

NPY_DT_PyArray_ArrFuncs_nonzero#

计算 numpy.nonzero 的 nonzero 函数,实现 PyArray_NonzeroFunc .

NPY_DT_PyArray_ArrFuncs_fill#

numpy.ndarray.fill 的数组填充函数,实现 PyArray_FillFunc .

NPY_DT_PyArray_ArrFuncs_fillwithscalar#

用于使用标量值填充数组的函数(用于 numpy.ndarray.fill ),实现 PyArray_FillWithScalarFunc .

NPY_DT_PyArray_ArrFuncs_sort#

长度为 NPY_NSORTS 的 PyArray_SortFunc 数组.如果设置,则允许为 numpy 实现的每种排序算法定义自定义排序实现.

NPY_DT_PyArray_ArrFuncs_argsort#

长度为 NPY_NSORTS 的 PyArray_ArgSortFunc 数组.如果设置,则允许为 numpy 实现的每种排序算法定义自定义 argsorting 实现.

宏和静态内联函数#

提供这些宏和静态内联函数是为了在使用 PyArray_DTypeMeta 实例时允许更易理解和更符合语言习惯的代码.

NPY_DTYPE(descr)#

返回一个指向给定描述符实例的 DType 的 PyArray_DTypeMeta * 指针.

static inline PyArray_DTypeMeta *NPY_DT_NewRef(PyArray_DTypeMeta *o)#

返回一个指向 DType 的新引用的 PyArray_DTypeMeta * 指针.

转换实用程序#

PyArg_ParseTuple 一起使用#

所有这些函数都可以在 PyArg_ParseTuple (…) 中与 “O&” 格式说明符一起使用,以自动将任何 Python 对象转换为所需的 C 对象.所有这些函数如果成功则返回 NPY_SUCCEED ,如果失败则返回 NPY_FAIL .所有这些函数的第一个参数是一个 Python 对象.第二个参数是将 Python 对象转换成的 C 类型的地址.

警告

请务必了解在使用这些转换函数时应采取哪些步骤来管理内存.这些函数可能需要释放内存,和/或根据您的使用情况更改特定对象的引用计数.

int PyArray_Converter(PyObject *obj, PyObject **address)#

将任何 Python 对象转换为 PyArrayObject .如果 PyArray_Check (obj) 为 TRUE,则其引用计数递增,并将引用放置在 address 中.如果 obj 不是数组,则使用 PyArray_FromAny 将其转换为数组.无论返回什么,当您完成使用 address 中的例程返回的对象后,都必须 DECREF 它.

int PyArray_OutputConverter(PyObject *obj, PyArrayObject **address)#

这是提供给函数的输出数组的默认转换器.如果 obj 是 Py_NoneNULL ,则 address 将为 NULL ,但调用将成功.如果 PyArray_Check ( obj) 为 TRUE,则它将在 address 中返回,而不递增其引用计数.

int PyArray_IntpConverter(PyObject *obj, PyArray_Dims *seq)#

将任何小于 NPY_MAXDIMS 的 Python 序列 obj 转换为 npy_intp 的 C 数组.Python 对象也可以是单个数字.seq 变量是指向具有成员 ptr 和 len 的结构的指针.成功返回时,seq ->ptr 包含指向内存的指针,必须通过调用 PyDimMem_FREE 释放该内存,以避免内存泄漏.对内存大小的限制允许方便地将此转换器用于旨在解释为数组形状的序列.

int PyArray_BufferConverter(PyObject *obj, PyArray_Chunk *buf)#

将具有(单段)缓冲区接口的任何 Python 对象 obj 转换为具有成员的变量,这些成员详细说明了对象对其内存块的使用.buf 变量是指向具有基本成员,ptr 成员,len 成员和 flags 成员的结构的指针. PyArray_Chunk 结构与 Python 的缓冲区对象是二进制兼容的(通过其在 32 位平台上的 len 成员和在 64 位平台上的 ptr 成员).返回时,base 成员设置为 obj(或者如果 obj 已经是指向另一个对象的缓冲区对象,则设置为其 base).如果您需要保留内存,请务必 INCREF base 成员.内存块由 buf ->ptr 成员指向,长度为 buf ->len.buf 的 flags 成员是 NPY_ARRAY_ALIGNED ,如果 obj 具有可写缓冲区接口,则设置 NPY_ARRAY_WRITEABLE 标志.

int PyArray_AxisConverter(PyObject *obj, int *axis)#

转换代表轴参数的 Python 对象 obj,以获得传递给采用整数轴的函数的正确值.具体来说,如果 obj 为 None,则 axis 设置为 NPY_RAVEL_AXIS ,C-API 函数会正确解释该值,该函数采用轴参数.

int PyArray_BoolConverter(PyObject *obj, npy_bool *value)#

将任何 Python 对象 obj 转换为 NPY_TRUENPY_FALSE ,并将结果放入值中.

int PyArray_ByteorderConverter(PyObject *obj, char *endian)#

将 Python 字符串转换为相应的字节顺序字符:’>’,’<’,’s’,’=’ 或 ‘|’.

int PyArray_SortkindConverter(PyObject *obj, NPY_SORTKIND *sort)#

将 Python 字符串转换为 NPY_QUICKSORT (以 ‘q’ 或 ‘Q’ 开头), NPY_HEAPSORT (以 ‘h’ 或 ‘H’ 开头), NPY_MERGESORT (以 ‘m’ 或 ‘M’ 开头)或 NPY_STABLESORT (以 ‘t’ 或 ‘T’ 开头)之一. NPY_MERGESORTNPY_STABLESORT 相互别名以实现向后兼容性,并且可能指的是取决于数据类型的多种稳定排序算法之一.

int PyArray_SearchsideConverter(PyObject *obj, NPY_SEARCHSIDE *side)#

将 Python 字符串转换为 NPY_SEARCHLEFT (以 ‘l’ 或 ‘L’ 开头) 或 NPY_SEARCHRIGHT (以 ‘r’ 或 ‘R’ 开头) 之一.

int PyArray_OrderConverter(PyObject *obj, NPY_ORDER *order)#

将 Python 字符串 ‘C’,’F’,’A’ 和 ‘K’ 转换为 NPY_ORDER 枚举 NPY_CORDER , NPY_FORTRANORDER , NPY_ANYORDERNPY_KEEPORDER .

int PyArray_CastingConverter(PyObject *obj, NPY_CASTING *casting)#

将 Python 字符串 ‘no’,’equiv’,’safe’,’same_kind’ 和 ‘unsafe’ 转换为 NPY_CASTING 枚举 NPY_NO_CASTING , NPY_EQUIV_CASTING , NPY_SAFE_CASTING , NPY_SAME_KIND_CASTINGNPY_UNSAFE_CASTING .

int PyArray_ClipmodeConverter(PyObject *object, NPY_CLIPMODE *val)#

将 Python 字符串 ‘clip’,’wrap’ 和 ‘raise’ 转换为 NPY_CLIPMODE 枚举 NPY_CLIP , NPY_WRAPNPY_RAISE .

int PyArray_ConvertClipmodeSequence(PyObject *object, NPY_CLIPMODE *modes, int n)#

将剪裁模式序列或单个剪裁模式转换为 NPY_CLIPMODE 值的 C 数组.在调用此函数之前,必须知道剪裁模式的数量 n.提供此函数是为了帮助函数允许每个维度使用不同的剪裁模式.

其他转换#

int PyArray_PyIntAsInt(PyObject *op)#

将所有类型的 Python 对象(包括数组和数组标量)转换为标准整数.如果出错,将返回 -1 并设置异常.您可能会发现以下宏很有用:

#define error_converting(x) (((x) == -1) && PyErr_Occurred())
npy_intp PyArray_PyIntAsIntp(PyObject *op)#

将所有类型的 Python 对象(包括数组和数组标量)转换为(平台指针大小的)整数.如果出错,将返回 -1 并设置异常.

int PyArray_IntpFromSequence(PyObject *seq, npy_intp *vals, int maxvals)#

将作为 seq 传入的任何 Python 序列(或单个 Python 数字)转换为(最多)maxvals 个指针大小的整数,并将它们放置在 vals 数组中.该序列可以小于 maxvals,因为返回的是转换后的对象数量.

包含和导入 C API#

要使用 NumPy C-API,您通常需要包含 numpy/ndarrayobject.h 头文件和 numpy/ufuncobject.h 用于一些 ufunc 相关功能 ( arrayobject.hndarrayobject.h 的别名).

这两个头文件导出了大多数相关功能.通常,任何使用 NumPy API 的项目都必须使用函数 PyArray_ImportNumPyAPI()import_array() 导入 NumPy. 在某些情况下,不需要需要 import_array() 的功能,因为您只需要类型定义.在这种情况下,包含 numpy/ndarratypes.h 就足够了.

对于典型的 Python 项目,多个 C 或 C++ 文件将被编译成一个共享对象(Python C 模块),并且 PyArray_ImportNumPyAPI() 应该在其模块初始化中被调用.

当您有一个 C 文件时,这将包括:

#include "numpy/ndarrayobject.h"

PyMODINIT_FUNC PyInit_my_module(void)
{
    if (PyArray_ImportNumPyAPI() < 0) {
        return NULL;
    }
    /* Other initialization code. */
}

但是,大多数项目将具有额外的 C 文件,这些文件都链接在一起形成一个 Python 模块. 在这种情况下,辅助 C 文件通常没有一个规范的位置来调用 PyArray_ImportNumPyAPI (虽然经常调用它也是可以的并且速度很快).

为了解决这个问题,NumPy 提供了以下模式,即在包含之前修改主文件以定义 PY_ARRAY_UNIQUE_SYMBOL :

/* Main module file */
#define PY_ARRAY_UNIQUE_SYMBOL MyModule
#include "numpy/ndarrayobject.h"

PyMODINIT_FUNC PyInit_my_module(void)
{
    if (PyArray_ImportNumPyAPI() < 0) {
        return NULL;
    }
    /* Other initialization code. */
}

而其他文件则使用:

/* Second file without any import */
#define NO_IMPORT_ARRAY
#define PY_ARRAY_UNIQUE_SYMBOL MyModule
#include "numpy/ndarrayobject.h"

您当然可以将定义添加到整个本地头文件中使用.您只需要确保主文件_不_定义 NO_IMPORT_ARRAY .

对于 numpy/ufuncobject.h 同样适用,但唯一的符号机制是 #define PY_UFUNC_UNIQUE_SYMBOL (两者都可以匹配).

此外,您可能希望添加一个 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION 以避免有关可能使用旧 API 的警告.

备注

如果您遇到访问冲突,请确保已正确导入 NumPy API,并且符号 PyArray_API 不为 NULL .当在调试器中时,此符号的实际名称将是 PY_ARRAY_UNIQUE_SYMBOL + PyArray_API ,例如上面的 MyModulePyArray_API .(例如,甚至在崩溃之前 printf("%p\n", PyArray_API); )

机制细节和动态链接#

该机制的主要部分是 NumPy 需要定义一个 void PyArray_API 表,供您查找所有函数.根据您的宏设置,这需要不同的路径,具体取决于是否定义了 NO_IMPORT_ARRAYPY_ARRAY_UNIQUE_SYMBOL :

  • 如果两者都没有定义,C-API 将声明为 static void PyArray_API ,因此它仅在使用 #include <numpy/arrayobject.h> 的编译单元/文件内可见.

  • 如果仅定义了 PY_ARRAY_UNIQUE_SYMBOL (可以为空),则它将声明为非静态的 void * ,允许其他链接的文件使用它.

  • 如果定义了 NO_IMPORT_ARRAY ,则该表声明为 extern void * ,这意味着它必须链接到不使用 NO_IMPORT_ARRAY 的文件.

PY_ARRAY_UNIQUE_SYMBOL 机制还会修改名称以避免冲突.

在 NumPy 版本发生变更: 2.1 版本更改了头文件,以避免在单个共享对象/dll 之外共享该表(在 Windows 上始终如此).有关详细信息,请参见 NPY_API_SYMBOL_ATTRIBUTE .

为了从另一个扩展模块中使用 C-API,必须调用 import_array 函数. 如果扩展模块包含在单个 .c 文件中,那么这就是需要做的全部. 但是,如果扩展模块涉及需要 C-API 的多个文件,则必须采取一些额外的步骤.

int PyArray_ImportNumPyAPI(void)#

确保已导入 NumPy C-API 并且可用. 成功时返回 0 ,如果无法导入 NumPy 并且设置了错误,则返回 -1 . 最好在模块初始化时调用它一次,但多次调用此函数非常轻量级.

在 2.0 版本加入: 此函数在 npy_2_compat.h 头文件中进行了反向移植.

import_array(void)#

必须在使用 C-API 的模块的初始化部分调用此函数. 它导入存储函数指针表的模块,并将正确的变量指向它. 此宏在错误时包含 return NULL; ,因此 PyArray_ImportNumPyAPI() 更适合自定义错误检查. 您还可以看到 _import_array() (一个函数,而不是宏,但如果它失败,您可能希望引发更好的错误)以及自定义返回值的变体 import_array1(ret) .

PY_ARRAY_UNIQUE_SYMBOL#
NPY_API_SYMBOL_ATTRIBUTE#

在 2.1 版本加入.

一个额外的符号,可用于共享例如超出共享对象边界的可见性. 默认情况下,NumPy 添加 C 的可见性隐藏属性 (如果可用): void __attribute__((visibility("hidden"))) PyArray_API; . 您可以通过定义 NPY_API_SYMBOL_ATTRIBUTE 来更改此设置,这将使其变为: void NPY_API_SYMBOL_ATTRIBUTE PyArray_API; (通过唯一符号进行额外的名称修改).

添加一个空的 #define NPY_API_SYMBOL_ATTRIBUTE 将具有与 NumPy 1.x 相同的行为.

备注

虽然您可以使用此宏来实现共享可见性,但 Windows 从未有过. 我们通常不鼓励共享超出共享边界,因为导入数组 API 包括 NumPy 版本检查.

NO_IMPORT_ARRAY#

ndarrayobject.h 包含之前定义 NO_IMPORT_ARRAY 表示 NumPy C API 导入在不同的文件中处理,并且包含机制将不会在此处添加. 您必须有一个没有定义 NO_IMPORT_ARRAY 的文件.

#define PY_ARRAY_UNIQUE_SYMBOL cool_ARRAY_API
#include <numpy/arrayobject.h>

另一方面,coolhelper.c 将在顶部包含:

#define NO_IMPORT_ARRAY
#define PY_ARRAY_UNIQUE_SYMBOL cool_ARRAY_API
#include <numpy/arrayobject.h>

您还可以将最后两行通用代码放入扩展本地头文件中,只要确保在 #including 该文件之前 #defined NO_IMPORT_ARRAY.

在内部,这些 #defines 的工作方式如下:

  • 如果两者都未定义,则 C-API 将声明为 static void* ,因此它仅在使用 #includes numpy/arrayobject.h 的编译单元中可见.

  • 如果 #defined 了 PY_ARRAY_UNIQUE_SYMBOL ,但没有 #defined NO_IMPORT_ARRAY ,则 C-API 将声明为 void* ,以便它对其他编译单元也可见.

  • 如果 #defined 了 NO_IMPORT_ARRAY ,无论是否 #defined PY_ARRAY_UNIQUE_SYMBOL ,C-API 都将被声明为 extern void* ,因此它应该在另一个编译单元中定义.

  • 每当 #defined PY_ARRAY_UNIQUE_SYMBOL 时,它也会更改保存 C-API 的变量的名称,该变量默认为 PyArray_API ,更改为宏 #defined 的任何内容.

检查 API 版本#

由于 python 扩展的使用方式与大多数平台上的常用库不同,因此某些错误无法在构建时甚至运行时自动检测到. 例如,如果您使用仅适用于 numpy >= 1.3.0 的函数构建扩展,并且稍后使用 numpy 1.2 导入扩展,您将不会收到导入错误(但在调用该函数时几乎肯定会出现段错误). 这就是为什么提供多个函数来检查 numpy 版本的原因. 宏 NPY_VERSIONNPY_FEATURE_VERSION 对应于用于构建扩展的 numpy 版本,而函数 PyArray_GetNDArrayCVersionPyArray_GetNDArrayCFeatureVersion 返回的版本对应于运行时 numpy 的版本.

ABI 和 API 兼容性的规则可以总结如下:

  • 每当 NPY_VERSION != PyArray_GetNDArrayCVersion() 时,扩展必须重新编译(ABI 不兼容).

  • NPY_VERSION == PyArray_GetNDArrayCVersion() 并且 NPY_FEATURE_VERSION <= PyArray_GetNDArrayCFeatureVersion() 意味着向后兼容的更改.

在 numpy 的每个版本中都会自动检测到 ABI 不兼容.API 不兼容检测是在 numpy 1.4.0 中添加的.如果你想用一个扩展二进制文件支持许多不同的 numpy 版本,你必须用尽可能低的 NPY_FEATURE_VERSION 构建你的扩展.

NPY_VERSION#

ndarray 对象的当前版本 (检查是否定义了此变量以保证正在使用 numpy/arrayobject.h 头文件).

NPY_FEATURE_VERSION#

C-API 的当前版本.

unsigned int PyArray_GetNDArrayCVersion(void)#

这只是返回 NPY_VERSION 的值.每当 ABI 级别发生向后不兼容的更改时, NPY_VERSION 就会更改.然而,因为它在 C-API 中,所以将此函数的输出与当前头文件中定义的值进行比较,可以测试 C-API 是否已更改,因此需要重新编译使用 C-API 的扩展模块.这会在 import_array 函数中自动检查.

unsigned int PyArray_GetNDArrayCFeatureVersion(void)#

这只是返回 NPY_FEATURE_VERSION 的值.只要 API 发生更改(例如,添加了一个函数), NPY_FEATURE_VERSION 就会更改.更改的值不一定需要重新编译.

内存管理#

char *PyDataMem_NEW(size_t nbytes)#
void PyDataMem_FREE(char *ptr)#
char *PyDataMem_RENEW(void *ptr, size_t newbytes)#

用于分配,释放和重新分配内存的函数. 除非被覆盖,否则这些函数在内部用于管理数组数据内存.

npy_intp *PyDimMem_NEW(int nd)#
void PyDimMem_FREE(char *ptr)#
npy_intp *PyDimMem_RENEW(void *ptr, size_t newnd)#

用于分配,释放和重新分配维度和步长内存的宏.

void *PyArray_malloc(size_t nbytes)#
void PyArray_free(void *ptr)#
void *PyArray_realloc(npy_intp *ptr, size_t nbytes)#

这些宏使用不同的内存分配器,具体取决于常量 NPY_USE_PYMEM . 当 NPY_USE_PYMEM 为 0 时,使用系统 malloc;如果 NPY_USE_PYMEM 为 1 时,则使用 Python 内存分配器.

NPY_USE_PYMEM#
int PyArray_ResolveWritebackIfCopy(PyArrayObject *obj)#

如果 obj->flags 具有 NPY_ARRAY_WRITEBACKIFCOPY ,此函数将清除标志, DECREF s obj->base 并使其可写,并将 obj->base 设置为 NULL. 然后,它将 obj->data 复制到 obj->base->data ,并返回复制操作的错误状态. 这与 PyArray_SetWritebackIfCopyBase 相反. 通常,一旦完成 obj ,就在 Py_DECREF(obj) 之前调用此函数. 它可以多次调用,或者使用 NULL 输入. 另请参见 PyArray_DiscardWritebackIfCopy .

如果未执行任何操作,则返回 0;如果出错,则返回 -1;如果执行了操作,则返回 1.

线程支持#

仅当在扩展模块的编译期间 NPY_ALLOW_THREADS 评估为 True 时,这些宏才有意义. 否则,这些宏等同于空格. Python 为每个 Python 进程使用单个全局解释器锁 (GIL),以便一次只能执行一个线程(即使在多 CPU 机器上). 当调用可能需要一段时间才能计算(并且对其他线程没有副作用,例如更新的全局变量)的已编译函数时,应释放 GIL,以便其他 Python 线程可以在执行耗时计算时运行. 这可以使用两组宏来实现. 通常,如果一组宏中的一个宏在代码块中使用,则必须在同一代码块中使用所有宏. NPY_ALLOW_THREADS 为真(定义为 1 ),除非构建选项 -Ddisable-threading 设置为 true - 在这种情况下, NPY_ALLOW_THREADS 为假 ( 0 ).

NPY_ALLOW_THREADS#

Group 1#

此组用于调用可能需要一些时间但不使用任何 Python C-API 调用的代码. 因此,应在其计算期间释放 GIL.

NPY_BEGIN_ALLOW_THREADS#

等效于 Py_BEGIN_ALLOW_THREADS , 只是它使用 NPY_ALLOW_THREADS 来确定宏是否被空格替换.

NPY_END_ALLOW_THREADS#

等效于 Py_END_ALLOW_THREADS , 只是它使用 NPY_ALLOW_THREADS 来确定宏是否被空格替换.

NPY_BEGIN_THREADS_DEF#

放在变量声明区域中. 此宏设置存储 Python 状态所需的变量.

NPY_BEGIN_THREADS#

在不需要 Python 解释器的代码(没有 Python C-API 调用)之前放置.此宏保存 Python 状态并释放 GIL.

NPY_END_THREADS#

在不需要 Python 解释器的代码之后放置.此宏获取 GIL 并从保存的变量中恢复 Python 状态.

void NPY_BEGIN_THREADS_DESCR(PyArray_Descr *dtype)#

仅在 dtype 不包含任意 Python 对象时释放 GIL 才有用,这些对象在循环执行期间可能需要 Python 解释器.

void NPY_END_THREADS_DESCR(PyArray_Descr *dtype)#

在已使用此宏的 BEGIN 形式释放 GIL 的情况下,重新获取 GIL 非常有用.

void NPY_BEGIN_THREADS_THRESHOLDED(int loop_size)#

仅当 loop_size 超过最小阈值时释放 GIL 才有用,当前设置为 500.应与 NPY_END_THREADS 匹配以重新获取 GIL.

第 2 组#

此组用于在释放 Python GIL 后重新获取它.例如,假设 GIL 已被释放(使用先前的调用),然后代码中的某些路径(可能在不同的子例程中)需要使用 Python C-API,那么这些宏可用于获取 GIL.这些宏基本上完成了前三个宏的逆向操作(获取 LOCK,保存其状态),然后使用保存的状态重新释放它.

NPY_ALLOW_C_API_DEF#

放置在变量声明区域中以设置必要的变量.

NPY_ALLOW_C_API#

在需要调用 Python C-API 的代码之前放置(当已知 GIL 已经释放时).

NPY_DISABLE_C_API#

在需要调用 Python C-API 的代码之后放置(以重新释放 GIL).

小技巧

永远不要在线程支持宏之后使用分号.

优先级#

NPY_PRIORITY#

数组的默认优先级.

NPY_SUBTYPE_PRIORITY#

默认子类型优先级.

NPY_SCALAR_PRIORITY#

默认标量优先级(非常小)

double PyArray_GetPriority(PyObject *obj, double def)#

返回 obj 的 __array_priority__ 属性(转换为 double),如果不存在该名称的属性,则返回 def. 为 PyArray_Type 类型的对象提供避免属性查找的快速返回.

默认缓冲区#

NPY_BUFSIZE#

用户可设置的内部缓冲区的默认大小.

NPY_MIN_BUFSIZE#

用户可设置的内部缓冲区的最小大小.

NPY_MAX_BUFSIZE#

用户可设置的缓冲区的最大允许大小.

其他常量#

NPY_NUM_FLOATTYPE#

浮点类型的数量

NPY_MAXDIMS#

NumPy 可以使用的最大维度数. 此值设置为 64,在 NumPy 2 之前为 32.

备注

我们建议您避免使用 NPY_MAXDIMS . 未来版本的 NumPy 可能会希望删除任何维度限制(以及常量). 创建此限制是为了 NumPy 可以在内部使用堆栈分配作为临时空间.

如果您的算法具有合理的维度最大数量,您可以检查并在本地使用它.

NPY_MAXARGS#

某些函数中可以使用的数组参数的最大数量. NumPy 2 之前通常为 32,现在为 64. 为了继续允许将其用作检查参数数量是否与 ufuncs 兼容的方法,此宏现在在运行时是依赖项.

备注

我们不鼓励以任何方式使用 NPY_MAXARGS ,除非它明确与检查已知的 NumPy 限制相关.

NPY_FALSE#

定义为 0,用于 Bool.

NPY_TRUE#

定义为 1,用于 Bool.

NPY_FAIL#

使用 PyArg_ParseTuple 类函数中的 “O&” 语法调用的失败转换器函数的返回值.

NPY_SUCCEED#

使用 PyArg_ParseTuple 类函数中的 “O&” 语法调用的成功转换器函数的返回值.

NPY_RAVEL_AXIS#

某些 NumPy 函数(主要是 Python 函数的 C 入口点)具有 axis 参数. 可以传递此宏作为 axis=None .

备注

此宏在运行时依赖于 NumPy 版本. 该值现在是最小整数. 但是,在 NumPy 1.x 上,使用了 NPY_MAXDIMS (当时设置为 32).

杂项宏#

int PyArray_SAMESHAPE(PyArrayObject *a1, PyArrayObject *a2)#

如果数组 a1 和 a2 具有相同的形状,则评估为 True.

PyArray_MAX(a, b)#

返回 a 和 b 的最大值. 如果 (a) 或 (b) 是表达式,它们将被评估两次.

PyArray_MIN(a, b)#

返回 a 和 b 的最小值. 如果 (a) 或 (b) 是表达式,它们将被评估两次.

void PyArray_DiscardWritebackIfCopy(PyArrayObject *obj)#

如果 obj->flags 具有 NPY_ARRAY_WRITEBACKIFCOPY ,此函数清除 flags, DECREF s obj->base 并使其可写,并将 obj->base 设置为 NULL. 与 PyArray_ResolveWritebackIfCopy 相比,它不尝试从 obj->base 复制数据. 这会撤消 PyArray_SetWritebackIfCopyBase . 通常,这在发生错误后,当您完成 obj 时,就在 Py_DECREF(obj) 之前调用. 它可以多次调用,或者使用 NULL 输入调用.

枚举类型#

enum NPY_SORTKIND#

一种特殊的变量类型,它可以取不同的值来表示正在使用的排序算法.

enumerator NPY_QUICKSORT#
enumerator NPY_HEAPSORT#
enumerator NPY_MERGESORT#
enumerator NPY_STABLESORT#

用作 NPY_MERGESORT 的别名,反之亦然.

enumerator NPY_NSORTS#

定义为排序的数量.由于需要向后兼容,因此固定为三个,因此 NPY_MERGESORTNPY_STABLESORT 相互别名,并且可以根据数据类型引用几种稳定的排序算法之一.

enum NPY_SCALARKIND#

一种特殊的变量类型,用于指示确定标量强制转换规则时区分的标量"种类"的数量.此变量可以采用以下值:

enumerator NPY_NOSCALAR#
enumerator NPY_BOOL_SCALAR#
enumerator NPY_INTPOS_SCALAR#
enumerator NPY_INTNEG_SCALAR#
enumerator NPY_FLOAT_SCALAR#
enumerator NPY_COMPLEX_SCALAR#
enumerator NPY_OBJECT_SCALAR#
enumerator NPY_NSCALARKINDS#

定义为标量种类的数量(不包括 NPY_NOSCALAR ).

enum NPY_ORDER#

一种枚举类型,指示应解释数组的元素顺序.创建全新的数组时,通常只使用 NPY_CORDER 和 NPY_FORTRANORDER,而当提供一个或多个输入时,顺序可以基于它们.

enumerator NPY_ANYORDER#

如果所有输入都是 Fortran 顺序,则为 Fortran 顺序,否则为 C 顺序.

enumerator NPY_CORDER#

C 顺序.

enumerator NPY_FORTRANORDER#

Fortran 顺序.

enumerator NPY_KEEPORDER#

尽可能接近输入的顺序,即使输入既不是 C 顺序也不是 Fortran 顺序.

enum NPY_CLIPMODE#

一种变量类型,指示在某些函数中应应用的剪裁类型.

enumerator NPY_RAISE#

大多数操作的默认值,如果索引超出范围,则引发异常.

enumerator NPY_CLIP#

如果索引超出范围,将其裁剪到有效范围.

enumerator NPY_WRAP#

如果索引超出范围,将其包装到有效范围.

enum NPY_SEARCHSIDE#

一种变量类型,指示返回的索引应该是第一个合适位置的索引(如果 NPY_SEARCHLEFT ),还是最后一个合适位置的索引(如果 NPY_SEARCHRIGHT ).

enumerator NPY_SEARCHLEFT#
enumerator NPY_SEARCHRIGHT#
enum NPY_SELECTKIND#

一种变量类型,指示正在使用的选择算法.

enumerator NPY_INTROSELECT#
enum NPY_CASTING#

一种枚举类型,指示数据转换应该有多宽松.这由 NumPy 1.6 中添加的迭代器使用,并且旨在在未来的版本中更广泛地使用.

enumerator NPY_NO_CASTING#

仅允许相同的类型.

enumerator NPY_EQUIV_CASTING#

允许相同的类型以及涉及字节交换的强制转换.

enumerator NPY_SAFE_CASTING#

仅允许不会导致值被舍入,截断或以其他方式更改的强制转换.

enumerator NPY_SAME_KIND_CASTING#

允许任何安全强制转换,以及相同类型的类型之间的强制转换.例如,此规则允许 float64 -> float32.

enumerator NPY_UNSAFE_CASTING#

允许任何强制转换,无论可能发生什么样的数据丢失.