Array 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 将基对象设置为拥有内存的对象.

如果设置了 NPY_ARRAY_WRITEBACKIFCOPY 标志,它具有不同的含义,即 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)#

从 ndarray arr 中获取位于 itemptr 指向位置的内置类型 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维索引处(ind的大小必须至少为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)中给定坐标处的元素,该ndarray分别必须具有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 的子类型. 数组具有由dims描述的nd维度. 新数组的数据类型描述符为 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风格的连续(对于data = NULL 或者flags& NPY_ARRAY_F_CONTIGUOUS 为非零非NULL数据,则flags为非零). 任何提供的dims和strides都会被复制到新分配的维度和新数组对象的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数组,则结果顺序为 NPY_FORTRANORDER ;否则为 NPY_CORDER . 当order为 NPY_KEEPORDER 时,结果顺序与prototype的顺序匹配,即使prototype的轴不是C或Fortran顺序.

如果 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) 将数组的内存设置为零.此函数不能用于创建flexible-type数组(未给出 itemsize).

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

围绕给定指针指向的 data 创建一个数组包装器.数组标志将具有默认值,即数据区域表现良好且 C 风格是连续的.数组的形状由长度为 nd 的 dims c 数组给出.数组的数据类型由 typenum 指示.如果 data 来自另一个引用计数的 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(评估为 byte)的内容填充 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 的 1 维数组,该数组以 step 作为增量,范围从 start 到 stop(不包括 stop). 等效于 arange (start, stop, step, dtype).

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

构造一个新的 1 维数组,其数据类型由 descr 确定,该数组以 step 作为增量,范围从 startstop (不包括 stop ). 等效于 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 参数的引用,该参数需要是一个 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

确保返回的数组在适当的边界上针对其数据类型进行了对齐. 对齐的数组具有数据指针和每个步幅因子,作为数据类型描述符的对齐因子的倍数.

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 (包括字节顺序) 或具有某些 requirements 时.

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_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, buf 导出(单段)缓冲区协议(或具有返回导出缓冲区协议的对象的 __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)#

如果 op 是 PyArray_Type 的实例(或子类),并且维度为 0,则计算结果为 true.

PyArray_IsScalar(op, cls)#

如果 op 是 Py{cls}ArrType_Type 的实例,则计算结果为真.

int PyArray_CheckScalar(PyObject *op)#

如果 op 是数组标量( PyGenericArrType_Type 的子类型的实例)或维度为 0 的 PyArray_Type 的实例(或子类),则计算结果为 true.

int PyArray_IsPythonNumber(PyObject *op)#

如果 op 是内置数值类型(int,float,complex,long,bool)的实例,则计算结果为 true.

int PyArray_IsPythonScalar(PyObject *op)#

如果 op 是一个内置的 Python 标量对象(int,float,complex,bytes,str,long,bool),则计算结果为 true.

int PyArray_IsAnyScalar(PyObject *op)#

如果 op 是一个 Python 标量对象(请参见 PyArray_IsPythonScalar )或一个数组标量( PyGenericArrType_Type 的子类型的实例),则计算结果为 true.

int PyArray_CheckAnyScalar(PyObject *op)#

如果 op 是一个 Python 标量对象(请参见 PyArray_IsPythonScalar ),一个数组标量( PyGenericArrType_Type 的子类型的实例)或一个维度为 0 的 PyArray_Type 的子类型的实例,则计算结果为 true.

数据类型访问器#

一些描述符属性可能并非总是定义,并且应该或不能直接访问.

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

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

PyObject *PyDataType_FIELDS(PyArray_Descr *descr)#

NULL , None 或结构化的 dtype 字段的字典.此字典不得被修改,NumPy 可能会在将来更改字段的存储方式.

这是与 np.dtype.fields 返回的字典相同的字典.

NpyAuxData *PyDataType_C_METADATA(PyArray_Descr *descr)#

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

PyArray_ArrayDescr *PyDataType_SUBARRAY(PyArray_Descr *descr)#

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

如果此项为非 NULL ,则此数据类型描述符是另一种数据类型描述符的 C 样式连续数组.换句话说,此描述符描述的每个元素实际上是某些其他基础描述符的数组.这最有用的是作为另一个数据类型描述符中字段的数据类型描述符.如果此项为非 NULL ,则 fields 成员应为 NULL (但是,基础描述符的 fields 成员可以为非 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_UNICODENPY_VOID ).

int PyDataType_ISUNSIZED(PyArray_Descr *descr)#

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

对于没有字段的结构化数据类型,此函数现在返回 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 元素被转换为 typenum 数据类型,该类型必须是枚举类型之一,而不是灵活类型.

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

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

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

从 1.6 开始,此函数仅调用 PyArray_CopyInto ,后者处理转换.

将 array in 中的元素转换到 array 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)#

如果数据类型为 fromtype (可以包括灵活类型)的数组可以根据转换规则 casting 安全地转换为数据类型为 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 中返回,并且一个 n 长度的 PyArrayObject 指针数组是返回值(如果发生错误,则为 NULL ).返回的数组必须由此例程的调用者释放(使用 PyDataMem_FREE ),并且其中的所有数组对象都必须 DECREF ‘d ,否则会发生内存泄漏.下面的示例模板代码显示了一个典型的用法:

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 的表示.返回的指针 ret 必须在使用完毕后使用 PyDataMem_FREE (ret) 释放.

char *PyArray_One(PyArrayObject *arr)#

指向新创建的,大小为 arr ->itemsize 的内存的指针,该内存保存该类型的 1 的表示.返回的指针 ret 在不再需要时必须使用 PyDataMem_FREE (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 注册为可从给定标量类型的 数据类型对象 descr 转换. 使用 scalar = NPY_NOSCALAR 注册数据类型为 descr 的数组可以安全地转换为类型编号为 totype 的数据类型.返回值是成功时为 0,失败时为 -1.

NPY_OBJECT的特殊函数#

警告

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

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

目前有一个意图是确保 NumPy 始终在读取对象数组之前对其进行初始化.任何未执行此操作的情况都将被视为 bug.未来,用户在从任何数组读取数据时,或许可以依赖于非 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 位置的所有对象的引用计数.如果 ptr 是结构化类型的开始,并且在该类型的任何偏移位置都有一个对象,那么这将(递归地)递增结构化类型中所有类似对象项目的引用计数.

int PyArray_XDECREF(PyArrayObject *op)#

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

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

根据数据类型 dtype 中记录的信息,XDECREF ptr 位置的所有类似对象条目.这是递归的,因此如果 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 属性包含有关数组使用的内存(由数据成员指向)的重要信息.此标志信息必须保持准确,否则可能导致奇怪的结果甚至段错误.

有 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) 将为 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 时,它的 “cast” 或 copy 需要实现 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;

未对齐的循环当前仅在强制转换中使用,并且永远不会在 ufuncs 中选取(ufuncs 创建一个临时副本以确保输入对齐).当定义了 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 是一组可选的辅助数据,可以传递到循环中 - 有助于打开和关闭可选行为或减少样板,从而允许类似的 ufuncs 共享循环实现或分配在多次步长循环调用中持续存在的空间.

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 以获取用于缩减的初始值.context 是 ArrayMethod 上下文,主要用于访问输入描述符.reduction_is_empty 指示缩减是否为空.当为空时,返回的值可能会有所不同.在这种情况下,它是一个“默认”值,可能与通常使用的“identity”值不同.例如:

  • 0.0sum([]) 的默认值.但是 -0.0 是正确的 identity,因为它保留了 sum([-0.0]) 的符号.

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

  • -infINT_MIN 对于 max 是 identity,但至少 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 是因为我们将来可能需要传入 Interpreter 状态或类似的东西,但我们不想传入完整的上下文(包含指向 dtypes ,方法,调用者的指针,这些对于 traverse 函数来说没有任何意义).我们目前假设这个上下文将来可以直接传递(对于结构化 dtypes ).

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 函数和 Typedefs#

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

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

从给定的 ArrayMethod spec 直接向 ufunc 添加循环.主要的 ufunc 注册函数.这会向 ufunc 添加新的实现/循环.它取代了 PyUFunc_RegisterLoopForType .

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

请注意,目前输出 dtypes 始终为 NULL ,除非它们也是签名的一部分.这是一个实现细节,将来可能会更改.但是,一般来说,promoter 不应需要输出 dtypes .为 ufunc 注册一个新的 promoter.第一个参数是 ufunc 以注册 promoter.第二个参数是一个 Python 元组,包含与 ufunc 的输入和输出数量相匹配的 DType 或 None .最后一个参数是 promoter,它是一个存储在 PyCapsule 中的函数.它会被传递 operation 和请求的 DType 签名,并且可以改变它以尝试搜索匹配的循环/promoter.

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

Promoter 函数的类型,必须使用名称 "numpy._ufunc_promoter" 包装到 PyCapsule 中.它会被传递 operation 和请求的 DType 签名,并且可以改变这些签名,以尝试搜索新的循环或 promoter,可以通过将输入转换为“提升的” DType 来完成 operation.

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

以某种方式检查执行浮点运算后的浮点错误,这种方式考虑了通过 numpy.errstate 配置的错误信号.使用 operation 的名称来用于错误消息中,并使用整数标志,该标志是 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.例如,一个单位 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).此函数会`reference <https://docs.python.org/3/c-api/intro.html?reference-count-details>`_ ”指向 PyArray_Descr ,并使用给定 ` dtype ,利用当前数组中指定 ` offset ` (以字节为单位)处的数据,返回一个新数组. 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 为负数,则使用最高可用协议).这是 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 的大小一致.要么 itemsizes 必须完全相同,要么 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 对象始终是二维的.因此, 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) except axis =None in Python is obtained by setting axis = NPY_MAXDIMS in C. 沿给定的轴提取 self 中由整数值 indices 指示的项目.clipmode 参数可以是 NPY_RAISE , NPY_WRAPNPY_CLIP ,以指示如何处理越界索引.ret 参数可以指定一个输出数组,而不是在内部创建一个.

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

等价于 self.put(values, indices, clipmode ) .将 values 中的值放入 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).返回一个数组,其中包含沿轴 axis 排序的 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 长度相同的一维整数索引数组,该数组按升序对其进行排序.这通常是对 PyArray_ArgSort (…) 的调用结果. 二分查找法用于查找所需的插入点.

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

等价于 ndarray.partition (self, ktharray, axis, kind).对数组进行分区,使由 ktharray 索引的元素的值位于它们在数组完全排序时所处的位置,并将所有小于 kth 的元素放在前面,并将所有等于或大于 kth 的元素放在 kth 元素之后.分区中所有元素的排序未定义.如果 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,如果不是 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 沿轴的最大元素与 self 沿轴的最小元素之间的差.当结果是单个元素时,返回一个 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).返回一个数组,该数组的每个由 axis 定义的 self 一维子数组中,如果所有元素均为 True,则该子数组的元素为 True.

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

等价于 ndarray.any (self, axis).返回一个数组,该数组的每个由 axis 定义的 self 一维子数组中,如果任何元素为 True,则该子数组的元素为 True.

函数#

数组函数#

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

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

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

  • ptr – (ctype 针对 1 维,ctype 针对 2 维,ctype 针对 3 维) 变量的地址,其中 ctype 是数据类型的等效 C 类型.返回时,ptr 可寻址为 1 维,2 维或 3 维数组.

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

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

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

备注

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

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 的倒数第二维的乘积和. 对于 2-d 数组,这是一个矩阵积. 两个数组都没有共轭.

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

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

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

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

注释

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

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

PyArray_Correlate 的更新版本,它使用 1d 数组的相关性的通常定义. 通过将 op1 乘以 op2 的移位版本并对结果求和,在每个输出点计算相关性. 由于移位,op1 和 op2 的定义范围之外的所需值被解释为零. mode 确定要返回的移位数量: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 是否是与 nd 维数组内存一致的 strides 数组,该数组具有形状 dims 和元素大小 elsize. 检查 newstrides 数组,以查看在每个方向上跳过提供的字节数是否意味着跳过的字节数超过 numbytes,而 numbytes 是可用内存段的假定大小. 如果 numbytes 为 0,则在假定 nd,dims 和 elsize 指的是单段数组的情况下,计算等效的 numbytes. 如果 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#

当使用由其他 dtypes 组成的更复杂的 dtypes(例如 struct dtype)时,创建操作 dtypes 的内部循环需要携带额外的数据. 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 的 free 函数,如果 auxdata 为 NULL,则不执行任何操作.

NpyAuxData *NPY_AUXDATA_CLONE(NpyAuxData *auxdata)#

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

数组迭代器#

从 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 一起使用. 此迭代器可用于编写类似于 ufuncs 所做的事情,其中最大轴的循环由单独的子例程完成. 如果 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 和 coordinates 成员设置为由 N 维 c 数组 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 当前指向的位置计算,边界定义邻域迭代器的形状,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 指示的数组标量对象,该对象从 data 指向的内存复制,并且如果 arr 中的数据不是机器字节顺序则进行交换.

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

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

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,但引用计数和错误检查除外. 成功时返回类型对象的新引用,失败时返回 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 设置字节顺序.所有引用的数据类型对象(在数据类型对象的 subdescrfields 成员中)也会被更改(递归).

newendian 的值是以下宏之一:

NPY_IGNORE#
NPY_SWAP#
NPY_NATIVE#
NPY_LITTLE#
NPY_BIG#

如果遇到 NPY_IGNORE 的字节顺序,则将其保留.如果 newendianNPY_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 并将结果 elsize 参数设置为所需的大小. typenumNPY_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 结构体类型的对象.

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

PyArray_DescrConverter2 类似,不同之处在于它会像编译器那样在字边界上对齐 C 结构体类型的对象.

数据类型提升和检查#

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 应该力求确保其 common-dtype 实现是结合律和交换律的!(主要是,有符号和无符号整数不是.)

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

一般来说,只要最通用的 dtype 严格大于或与所有其他 dtype 兼容,这种方法总是有效.例如,将 float16 与任何其他浮点数,整数或无符号整数进行提升,再次得到一个浮点数.

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 中调用,该 sentinel 值表示零,如果由于某种原因零填充数组不足以满足要求. 实现 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 变量是指向具有 base,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 ,并将结果放入 value 中.

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

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

其他转换#

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 头文件,以及一些 ufunc 相关功能的 numpy/ufuncobject.h ( 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 从来没有共享可见性,但你可以使用这个宏来实现它.我们通常不鼓励在共享边界线之外进行共享,因为导入 array 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 的编译单元中可见.

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

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

  • 每当 PY_ARRAY_UNIQUE_SYMBOL 是 #defined 的,它也会更改保存 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() 表示向后兼容的更改.

ABI 不兼容会在每个 numpy 版本中自动检测到. 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 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 线程可以在执行耗时计算时运行. 这可以使用两组宏来完成. 通常,如果在代码块中使用组中的一个宏,则必须在同一代码块中使用所有宏. 除非构建选项 -Ddisable-threading 设置为 true ,否则 NPY_ALLOW_THREADS 为 true(定义为 1 ) - 在这种情况下, NPY_ALLOW_THREADS 为 false ( 0 ).

NPY_ALLOW_THREADS#

组 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 对象(在循环执行期间可能需要 Python 解释器)时,才可用于释放 GIL.

void NPY_END_THREADS_DESCR(PyArray_Descr *dtype)#

适用于恢复使用此宏的 BEGIN 形式释放的 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__ 属性(转换为双精度浮点数),如果不存在该名称的属性,则返回 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.为了继续允许将其用作检查参数数量是否与 ufunc 兼容的方式,此宏现在依赖于运行时.

备注

我们不鼓励任何不明确与检查已知的 NumPy 限制相关的 NPY_MAXARGS 使用.

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 ,则此函数清除标志, DECREF 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#

定义为排序的数量.由于需要向后兼容,因此它被固定为3,因此 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 顺序,否则为 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#

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