数组 API#

一流智慧的测试是能够同时持有两种
在同一时间心中持有相反的想法,并且仍然保留
功能能力.
F. Scott Fitzgerald
对于一项成功的技术,现实必须优先于公众
关系,因为自然不能被愚弄.
理查德·P·费曼

数组结构和数据访问#

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

int PyArray_NDIM(PyArrayObject *arr)#

数组中的维度数量.

int PyArray_FLAGS(PyArrayObject *arr)#

返回一个表示 数组标志 的整数.

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 无法处理不同数据类型之间的任意转换.

void PyArray_ENABLEFLAGS(PyArrayObject *arr, int flags)#

在 1.7 版本加入.

启用指定的数组标志.此函数不进行验证,并假设你知道自己在做什么.

void PyArray_CLEARFLAGS(PyArrayObject *arr, int flags)#

在 1.7 版本加入.

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

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

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

npy_intp *PyArray_DIMS(PyArrayObject *arr)#

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

npy_intp *PyArray_SHAPE(PyArrayObject *arr)#

在 1.7 版本加入.

这是 PyArray_DIMS 的一个同义词,命名为与 Python 中的 shape 用法一致.

npy_intp *PyArray_STRIDES(PyArrayObject *arr)#

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

npy_intp PyArray_DIM(PyArrayObject *arr, int n)#

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

npy_intp PyArray_STRIDE(PyArrayObject *arr, int n)#

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

npy_intp PyArray_ITEMSIZE(PyArrayObject *arr)#

返回此数组元素的itemsize.

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

npy_intp PyArray_SIZE(PyArrayObject *arr)#

返回数组的总大小(以元素数量计).

npy_intp PyArray_Size(PyArrayObject *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 是当前数组将在复制解析时复制到的数组.这种为两个功能重载 base 属性的做法可能会在 NumPy 的未来版本中更改.

PyArray_Descr *PyArray_DESCR(PyArrayObject *arr)#

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

PyArray_Descr *PyArray_DTYPE(PyArrayObject *arr)#

在 1.7 版本加入.

PyArray_DESCR 的同义词,命名为与 Python 中的 ‘dtype’ 用法一致.

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

从 ndarray 中获取一个内置类型的 Python 对象,*arr*,在 itemptr 指向的位置.如果失败,返回 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-array ind 给出的 N 维索引处(该数组的大小必须至少为 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*,该元素必须分别具有 1、2、3 或 4 个维度(这不会被检查).相应的 ijkl 坐标可以是任何整数,但将被解释为 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__ 方法的对象.

如果 dataNULL,那么将分配新的未初始化内存,并且 flags 可以是非零值以指示 Fortran 风格的连续数组.使用 PyArray_FILLWBYTE 来初始化内存.

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

此外,如果 data 是非空的,那么 strides 也可以提供.如果 stridesNULL ,那么数组的步长将计算为 C 风格的连续(默认)或 Fortran 风格的连续(flags 对于 data = NULLflags & NPY_ARRAY_F_CONTIGUOUS 对于非空的 data 是非零的).任何提供的 dimsstrides 都会被复制到新数组对象中新分配的维度和步长数组中.

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

如果提供了 data ,它必须保持活动状态直到数组的生命周期结束.管理这一点的一种方法是使用 PyArray_SetBaseObject

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

在 1.6 版本加入.

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

orderNPY_ANYORDER 时,结果顺序是 NPY_FORTRANORDER 如果 prototype 是一个 fortran 数组,否则是 NPY_CORDER.当 orderNPY_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_numitemsize 指定数据类型描述符,其中 type_num 对应于内置(或用户定义)类型.如果该类型总是有相同的字节数,则忽略 itemsize.否则,itemsize 指定该数组的特定大小.

警告

如果数据传递给 PyArray_NewFromDescrPyArray_New,这个内存必须在新数组被删除之前不被释放.如果这个数据来自另一个 Python 对象,这可以通过对该对象使用 Py_INCREF 并设置新数组的 base 成员指向该对象来实现.如果传递了步长,它们必须与维度、元素大小和数组数据一致.

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

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

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

创建一个围绕由给定指针指向的 data 的数组包装器.数组标志将有一个默认值,即数据区域表现良好且是C风格的连续.数组的形状由长度为 nddims c数组给出.数组的数据类型由 typenum 指示.如果数据来自另一个引用计数的Python对象,在传递指针后应增加该对象的引用计数,并且返回的ndarray的base成员应指向拥有数据的Python对象.这将确保在返回的数组存在时,提供的内存不会被释放.

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

此函数窃取对 descr 的引用.

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

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 的一维数组,其范围从 startstop (不包括),增量为 step .等效于 arange (start, stop, step, dtype).

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

构造一个新的由 descr 决定数据类型的 1 维数组,该数组从 startstop``(不包括)以 ``step 为增量.等同于 arange( start, stop, step, typenum ).

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

在 1.7 版本加入.

这个函数 窃取一个引用obj 并将其设置为 arr 的 base 属性.

如果你通过传递自己的内存缓冲区作为参数来构造一个数组,你需要将数组的 base 属性设置为确保内存缓冲区的生命周期是合适的.

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

如果提供的对象是一个数组,此函数会遍历 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)维度数量,以及其他*requirements*.此函数**窃取**对dtype参数的引用,该参数需要是:c:type:PyArray_Descr`结构,指示所需的数据类型(包括所需的字节顺序).*dtype*参数可以是``NULL`,表示任何数据类型(和字节顺序)都可接受.除非:c:data:NPY_ARRAY_FORCECAST`存在于``flags``中,否则如果无法从对象安全地获取数据类型,此调用将生成错误.如果你想对*dtype*使用``NULL``并确保数组不被交换,则使用:c:func:`PyArray_CheckFromAny.深度参数的值为0会导致该参数被忽略.以下任意数组标志可以添加(例如使用|)到*requirements*参数中.如果你的代码可以处理一般情况(例如跨步、字节交换或未对齐的数组),则*requirements*可能为0.此外,如果*op*还不是数组(或未暴露数组接口),则将创建一个新数组(并使用序列协议从*op*填充).新数组将具有:c:data:`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 一开始就不可写,或者它不是一个数组,则会引发错误.

数组标志的组合 也可以添加.

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* 中的规范)和 :c:data:`NPY_ARRAY_ELEMENTSTRIDES,这表明数组应在步长是元素大小的倍数的意义上对齐.

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

PyArray_FromAny 的特殊情况,当 op 已经是一个数组,但它需要是特定 newtype*(包括字节顺序)或具有某些 *requirements 时.

PyObject *PyArray_FromStructInterface(PyObject *op)#

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

PyObject *PyArray_FromInterface(PyObject *op)#

根据数组接口协议,从暴露 __array_interface__ 属性的 Python 对象返回一个 ndarray 对象.如果对象不包含此属性,则返回对 Py_NotImplemented 的借用引用.

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

从暴露 __array__ 方法的 Python 对象返回一个 ndarray 对象.第三方实现的 __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,要求设置为 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 并带有要求 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 并将要求设置为 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 (或具有返回导出缓冲区协议对象的属性 __buffer__ 的对象)构造一个单一类型的 一维 ndarray.首先尝试可写缓冲区,然后尝试只读缓冲区.返回数组的 NPY_ARRAY_WRITEABLE 标志将反映哪一个成功.数据假定从对象内存起始位置的 offset 字节开始.缓冲区中的数据类型将根据数据类型描述符 dtype 进行解释.如果 count 为负数,则将根据缓冲区大小和请求的项大小确定,否则,``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 参数,指示结果数组必须具有的属性.可以强制执行的可用要求包括 NPY_ARRAY_C_CONTIGUOUSNPY_ARRAY_F_CONTIGUOUSNPY_ARRAY_ALIGNEDNPY_ARRAY_WRITEABLENPY_ARRAY_NOTSWAPPEDNPY_ARRAY_ENSURECOPYNPY_ARRAY_WRITEBACKIFCOPYNPY_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 ,允许同时提供 typenumflags 参数.

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

类似于 PyArray_FromAny ,除了数据类型是使用类型编号指定的.:c:func:PyArray_DescrFromType (typenum) 直接传递给 PyArray_FromAny .如果 NPY_ARRAY_ENSURECOPY 作为要求传递进来,这个宏还会在要求中添加 NPY_ARRAY_DEFAULT .

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

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

处理类型#

Python 类型的常规检查#

int PyArray_Check(PyObject *op)#

如果 op 是一个类型为 PyArray_Type 子类型的 Python 对象,则评估为真.

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

如果 opPy{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 的子类型实例)或 PyArray_Type 的子类型实例,其维度为 0,则评估为真.

数据类型访问器#

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

在 2.0 版本发生变更: 在 NumPy 2.0 之前,ABI 是不同的,但对于用户 DTypes 来说是不必要的庞大.这些访问器都是在 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)#

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

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

NULLNone 或结构化 dtype 字段的字典,此字典不得被突变,NumPy 可能会在未来改变字段的存储方式.

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

NpyAuxData *PyDataType_C_METADATA(PyArray_Descr *descr)#

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

PyArray_ArrayDescr *PyDataType_SUBARRAY(PyArray_Descr *descr)#

关于一个子数组数据类型的信息,等同于 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 宏,参数是一个表示枚举数组数据类型的整数.对于数组类型检查宏,参数必须是一个可以被直接解释为 PyArrayObject*PyObject*.

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

Type 表示一个无符号整数.

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

Type 表示一个字符串数据类型.

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

类型表示一种灵活的数组类型( NPY_STRINGNPY_UNICODENPY_VOID ).

int PyDataType_ISUNSIZED(PyArray_Descr *descr)#

类型没有附加的大小信息,并且可以调整大小.应该仅在灵活的数据类型上调用.附加到数组的类型总是有大小,因此该宏的数组形式不存在.

在 1.18 版本发生变更.

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

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

Type 表示一个用户定义的类型.

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

Type 表示对象数据类型.

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

Type 表示布尔数据类型.

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

类型有与之关联的字段.

int PyArray_ISNOTSWAPPED(PyArrayObject *m)#

如果 ndarray m 的数据区域根据数组的数据类型描述符处于机器字节顺序,则评估为真.

int PyArray_ISBYTESWAPPED(PyArrayObject *m)#

如果 ndarray m 的数据区域根据数组的数据类型描述符**不**在机器字节顺序中,则评估为真.

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

如果 type1type2 实际上在这个平台上代表等效的类型(每个类型的 fortran 成员被忽略),则返回 NPY_TRUE.例如,在 32 位平台上,:c:data:NPY_LONGNPY_INT 是等效的.否则返回 NPY_FALSE.

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

如果 a1a2 是对于此平台具有等效类型的数组,则返回 NPY_TRUE.

npy_bool PyArray_EquivTypenums(int typenum1, int typenum2)#

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

int PyArray_EquivByteorders(int b1, int b2)#

如果字节顺序字符 b1b2NPY_LITTLE, NPY_BIG, NPY_NATIVE, NPY_IGNORE )相等或等效于它们对本地字节顺序的指定,则为真.因此,在小端机器上 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)#

返回一个指定 type 的新数组,将 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)#

在 1.6 版本加入.

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

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

在 1.6 版本加入.

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

这几乎与 PyArray_CanCastTypeTo(PyArray_MinScalarType(arr), totype, casting) 的结果相同,但它还处理了一个特殊情况,因为对于具有相同位数的类型,uint 值的集合不是 int 值的子集.

PyArray_Descr *PyArray_MinScalarType(PyArrayObject *arr)#

在 1.6 版本加入.

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

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

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

在 1.6 版本加入.

找到最小大小和种类的数据类型,*type1* 和 type2 可以安全地转换为该类型.此函数是对称且可结合的.字符串或unicode结果将具有适当的大小,以存储输入类型转换为字符串或unicode的最大值.

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

在 1.6 版本加入.

这适用于类型提升到所有输入数组和dtype对象,使用NumPy规则来组合标量和数组,以确定与给定操作数进行操作的输出类型.这与ufuncs产生的相同结果类型.

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

int PyArray_ObjectType(PyObject *op, int mintype)#

此函数已被 PyArray_MinScalarType 和/或 PyArray_ResultType 取代.

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

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

这个功能在1.6版本中引入的迭代器 NpyIter 很大程度上被取代了,带有标志 NPY_ITER_COMMON_DTYPE 或者所有操作数使用相同的dtype参数.

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

在 1.18.0 版本发生变更: 现在,标量和零维数组的混合会产生一个能够保存标量值的类型.以前优先考虑的是数组的dtype.

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 已经注册(仅通过指针地址检查),则返回先前分配的类型编号.

已知用户DTypes的数量存储在 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*,作为可以从给定的 scalar 类型的数据类型对象 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)#

一个函数,用于在位置 ptr 处对数据类型 dtype 中记录的所有类似对象的项目进行 XDECREF.这个操作是递归的,因此如果 dtype 本身具有包含类似对象项目的数据类型的字段,所有类似对象的字段都将被 XDECREF 'd.

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

前提条件:arrbase 的一个副本(尽管可能具有不同的步幅、顺序等).设置 NPY_ARRAY_WRITEBACKIFCOPY 标志和 arr->base,并将 base 设置为 READONLY.在调用 Py_DECREF 之前调用 PyArray_ResolveWritebackIfCopy,以便将任何更改复制回 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.strides[dim] 的步幅可能是 任意的 如果 arr.shape[dim] == 1 或数组没有元素.通常情况下,C 风格连续数组的 self.strides[-1] == self.itemsize 或 Fortran 风格连续数组的 self.strides[0] == self.itemsize 并不成立.从 C API 访问数组 itemsize 的正确方法是 PyArray_ITEMSIZE(arr).

NPY_ARRAY_OWNDATA#

数据区域归此数组所有.不应手动设置,而是创建一个包含数据的 PyObject 并将其设置为数组的基础对象.有关示例,请参见 test_mem_policy 中的测试.

NPY_ARRAY_ALIGNED#

数据区域和所有数组元素都适当地对齐.

NPY_ARRAY_WRITEABLE#

数据区域可以被写入.

请注意,上述3个标志是这样定义的,以便一个新的、行为良好的数组将这些标志定义为真.

NPY_ARRAY_WRITEBACKIFCOPY#

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

这是一个特殊的标志,如果在 PyArray_FromAny 中用户需要某些标志并且必须复制某些其他数组(并且用户要求在这种情况下设置此标志),则设置此标志.然后,基属性指向”行为不端”的数组(设置为只读).:c:func:PyArray_ResolveWritebackIfCopy 将把其内容复制回”行为不端”的数组(如有必要则进行转换),并将”行为不端”的数组重置为 NPY_ARRAY_WRITEABLE.如果”行为不端”的数组一开始不是 NPY_ARRAY_WRITEABLE,那么 PyArray_FromAny 会返回一个错误,因为 NPY_ARRAY_WRITEBACKIFCOPY 是不可能的.

PyArray_UpdateFlags (obj, flags) 将更新 obj->flagsflags,可以是 NPY_ARRAY_C_CONTIGUOUSNPY_ARRAY_F_CONTIGUOUSNPY_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(PyObject *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(PyObject *arr)#

如果 arr 是 C 风格的连续的,则评估为真.

int PyArray_IS_F_CONTIGUOUS(PyObject *arr)#

如果 arr 是 Fortran 风格的连续数组,则评估为真.

int PyArray_ISFORTRAN(PyObject *arr)#

如果 arr 是 Fortran 风格的连续且 不是 C 风格的连续,则评估为真.:c:func:PyArray_IS_F_CONTIGUOUS 是测试 Fortran 风格连续性的正确方法.

int PyArray_ISWRITEABLE(PyObject *arr)#

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

int PyArray_ISALIGNED(PyObject *arr)#

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

int PyArray_ISBEHAVED(PyObject *arr)#

如果 arr 的数据区域根据其描述符对齐、可写且在机器字节顺序中,则评估为真.

int PyArray_ISBEHAVED_RO(PyObject *arr)#

如果 arr 的数据区域是对齐的并且是机器字节顺序,则评估为真.

int PyArray_ISCARRAY(PyObject *arr)#

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

int PyArray_ISFARRAY(PyObject *arr)#

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

int PyArray_ISCARRAY_RO(PyObject *arr)#

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

int PyArray_ISFARRAY_RO(PyObject *arr)#

如果 arr 的数据区域是 Fortran 风格的连续、对齐且在机器字节顺序中,则评估为真 .

int PyArray_ISONESEGMENT(PyObject *arr)#

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

void PyArray_UpdateFlags(PyArrayObject *arr, int flagmask)#

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

警告

在执行可能导致标志更改的数组操作时,保持标志更新(使用 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)#

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

method 是指向底层 cast 或 ufunc loop 的指针.未来我们可能会公开这个结构体,但现在这是一个不透明的指针,无法检查该方法.*dtypes* 是一个 nargs 长度的 PyArray_DTypeMeta 指针数组,*given_descrs* 是一个 nargs 长度的输入描述符实例数组(如果用户没有提供输出,输出描述符可能为 NULL),*loop_descrs* 是一个 nargs 长度的描述符数组,必须由 resolve descriptors 实现填充.*view_offset* 目前仅对 casts 感兴趣,通常可以忽略.当 cast 不需要任何操作时,可以通过将 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还是cast)的一维跨步循环.在大多数情况下,``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;

未对齐的循环当前仅在强制转换中使用,并且永远不会在 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)#

查询用于归约的初始值的数组方法.*context* 是数组方法的上下文,主要用于访问输入描述符.*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 时应设置 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#

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

Typedefs#

下面描述了可以由 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 钩子进行零填充.这些对于处理存储嵌入式引用或堆分配数据的数组最为有用.

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

传入 traverse_context 是因为我们可能需要在将来传入解释器状态或类似的内容,但我们不想传入一个完整的上下文(带有指向 dtypes、方法、调用者的指针,这些对于一个遍历函数都没有意义).我们假设这个上下文在将来可以简单地传递(用于结构化 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)#

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

它应该设置遍历循环所需的标志,并将 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)#

请注意,当前输出 dtypes 总是 NULL,除非它们也是签名的一部分.这是一个实现细节,将来可能会改变.然而,一般来说,推动者不需要输出 dtypes.为 ufunc 注册一个新的推动者.第一个参数是要注册推动者的 ufunc.第二个参数是一个包含 DTypes 或 None 的 Python 元组,匹配 ufunc 的输入和输出数量.最后一个参数是一个存储在 PyCapsule 中的函数.它传递操作和请求的 DType 签名,并可以对其进行变异,以尝试为匹配的循环/推动者进行新的搜索.

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_DIVIDEBYZERONPY_FPE_OVERFLOWNPY_FPE_UNDERFLOWNPY_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实现的DTypes有用.例如,一个单位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).这个函数 窃取引用PyArray_Descr 并返回一个使用当前数组中数据的新数组,该数组的 dtype 在指定字节 offset 处.`offset` 加上新数组类型的大小必须小于 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 不变.

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

等同于 ndarray.copy (self, fortran).复制 数组.返回的数组总是对齐且可写的,数据解释与旧数组相同.如果 orderNPY_CORDER,则返回一个 C 风格连续的数组.如果 orderNPY_FORTRANORDER,则返回一个 Fortran 风格连续的数组.如果 orderNPY_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)#

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

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

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

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

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

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.

如果 dtypeNULL,那么返回的数组将具有与 self 相同的数据类型.新的数据类型必须与 self 的大小一致.项大小必须相同,或者 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).返回一个新视图,其中形状中所有长度为1的维度都被移除.

警告

矩阵对象总是二维的.因此,:c:func:PyArray_Squeeze 对矩阵子类的数组没有影响.

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

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

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,:c:data:NPY_CORDER,或 NPY_FORTRANORDER.目前它没有效果.最终它可以用于确定在构建不同维度的数组时调整大小操作应如何查看数据.成功时返回 None,错误时返回 NULL.

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

等同于 ndarray.transpose (self, permute).根据数据结构 permute 置换 ndarray 对象 self 的轴并返回结果.如果 permuteNULL,则结果数组的轴将被反转.例如,如果 self 的形状是 \(10 imes20 imes30\),而 permute .ptr 是 (0,2,1),则结果的形状是 \(10 imes30 imes20\).如果 permuteNULL,结果的形状是 \(30 imes20 imes10\).

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

等同于 ndarray.flatten (self, order).返回一个一维数组的副本.如果 orderNPY_FORTRANORDER,元素按 Fortran 顺序(第一维度变化最快)扫描.如果 orderNPY_CORDER,``self`` 的元素按 C 顺序(最后一维度变化最快)扫描.如果 orderNPY_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 中提取由整数值 indices 指示的项目,沿着给定的 axis.clipmode 参数可以是 NPY_RAISENPY_WRAPNPY_CLIP,以指示如何处理越界索引.*ret* 参数可以指定一个输出数组,而不是内部创建一个.

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

等同于 self.put(values, indices, clipmode ).将 values 放入 self 中对应的(扁平化的)*indices* 位置.如果 values 太小,则会根据需要重复.

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

mask 中对应位置(使用扁平化上下文)为真时,将 values 放入 self 中.*mask* 和 self 数组必须具有相同数量的元素.如果 values 太小,则会根据需要重复.

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

等同于 ndarray.repeat (self, op, axis).复制 self 的元素,沿给定的 axis 重复 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) 来包装值 < 0,并通过减去 len(op) 来包装值 >=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 是一个定义了字段的 dtype,则使用 self->descr->names 来确定排序顺序.第一个字段相等的比较将使用第二个字段,依此类推.要更改结构化数组的排序顺序,请创建一个具有不同名称顺序的新 dtype,并使用该新 dtype 构造数组的视图.

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 的元素放在后面.分区内的所有元素的顺序未定义.如果 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 ).返回由 axis1axis2 定义的二维数组的 offset 对角线.

npy_intp PyArray_CountNonzero(PyArrayObject *self)#

在 1.6 版本加入.

计算数组对象 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 为真的元素.

计算#

小技巧

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

备注

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

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

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

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

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

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

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

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

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

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

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

备注

rtype 参数指定缩减应在其上进行的 数据类型.如果数组的数据类型不足以处理输出,这一点很重要.默认情况下,所有整数数据类型至少会变得与 NPY_LONG 一样大,用于”加”和”乘”ufuncs(它们构成了均值、总和、累积总和、乘积和累积乘积函数的基础).

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

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

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

等同于 ndarray.trace (self, offset, axis1, axis2, rtype).返回由 axis1axis2 变量定义的二维数组的对角元素之和(使用 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^{- extrm{decimals}}\) 位,因此负的 decimals 会导致四舍五入到最近的十、百等.如果 out 是 NULL,则创建输出数组,否则输出被放置在 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).返回沿 axisself 中元素的 1-d 向量和.在将数据转换为数据类型 rtype 后执行求和.

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

等同于 ndarray.cumsum (self, axis, rtype).返回沿 axisself 元素的累积 1-d 和.在将数据转换为数据类型 rtype 后执行求和.

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

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

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

等同于 ndarray.cumprod (self, axis, rtype).返回沿 axisself 元素的 1-d 累积乘积.在将数据转换为数据类型 rtype 后执行乘积.

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

等同于 ndarray.all (self, axis).返回一个数组,其中包含 selfaxis 定义的每个 1-d 子数组中所有元素都为 True 的 True 元素.

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

等同于 ndarray.any (self, axis).返回一个数组,其中对于 selfaxis 定义的每个 1-d 子数组,只要有一个元素为 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 ndarrays.

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

  • ptr – 一个(ctype* 表示一维,ctype** 表示二维,或 ctype*** 表示三维)变量的地址,其中 ctype 是数据类型的等效 C 类型.返回时,*ptr* 可以作为一维、二维或三维数组进行寻址.

  • dims – 一个包含数组对象形状的输出数组.该数组为任何将进行的循环提供边界.

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

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

备注

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

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

计算 obj1obj2 最后维度上的乘积和.两个数组都不进行共轭.

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

计算 obj1 最后一个维度与 obj2 倒数第二个维度的乘积和.对于二维数组,这是一个矩阵乘积.两个数组都不进行共轭.

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

在 1.6 版本加入.

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

在 1.6 版本加入.

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

更多详情请参见 einsum 函数.

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

计算一维数组 op1op2 的一维相关性.相关性在每个输出点通过将 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).否则,必须给出 xy,并且返回的对象形状与 condition 相同,并且 condition 分别为 True 或 False 时,对象的元素为 xy.

其他功能#

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

确定 newstrides 是否是一个与具有形状 dims 和元素大小 elsizend 维数组内存一致的步幅数组.检查 newstrides 数组,以查看在每个方向上按提供的字节数跳跃是否会意味着跳跃超过 numbytes ,这是假设的可用内存段的大小.如果 numbytes 为 0,则假设 nddimselsize 指的是单段数组,计算等效的 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.

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

在 1.7.0 版本加入.

type NpyAuxData#

当使用由其他数据类型组成的更复杂的数据类型(如结构数据类型)时,创建操作这些数据类型的内部循环需要携带额外的数据.NumPy 通过结构 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维数组元素的简单方法,如 示例 中所见,该示例提供了更多关于从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)#

返回一个数组迭代器,该迭代器被广播以迭代为由 dimensionsnd 提供的形状的数组.

int PyArrayIter_Check(PyObject *op)#

如果 op 是一个数组迭代器(或数组迭代器类型的子类的实例),则评估为真.

void PyArray_ITER_RESET(PyObject *iterator)#

迭代器 重置到数组的开始位置.

void PyArray_ITER_NEXT(PyObject *iterator)#

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

void *PyArray_ITER_DATA(PyObject *iterator)#

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

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

iterator 的索引、dataptr 和坐标成员设置为由 N 维 c 数组 destination 指示的数组中的位置,该数组的大小至少为 iterator ->nd_m1+1.

void PyArray_ITER_GOTO1D(PyObject *iterator, npy_intp index)#

迭代器 索引和数据指针设置为数组中由整数 索引 指示的位置,该索引指向 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 \(^{ extrm{th}}\) 迭代器的数据指针.

void PyArray_MultiIter_NEXTi(PyObject *multi, int i)#

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

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

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

void PyArray_MultiIter_GOTO1D(PyObject *multi, npy_intp index)#

在多迭代器对象 multi 中,将每个迭代器推进到展平广播数组中 index 对应的相应位置.

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维)索引到多迭代器对象的广播结果中.

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 版本通常针对速度进行了优化,因此循环应该在不需要大步幅跳跃的轴上执行.

邻域迭代器#

在 1.4.0 版本加入.

邻域迭代器是迭代器对象的子类,可用于迭代点的邻域.例如,您可能希望迭代 3D 图像的每个体素,并且对于每个这样的体素,迭代一个超立方体.邻域迭代器自动处理边界,从而使这种代码比手动处理边界更容易编写,但代价是轻微的开销.

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

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

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

模式应为以下之一:

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 本身可以是一个邻域迭代器:这可以用于例如自动边界处理.

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

  • 如果 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 的数组标量对象.如果 dtypevoid 标量,或者设置了 NPY_USE_GETITEM 标志并且已知 getitem 方法在不检查它是否为 NULL 的情况下使用 arr 参数,则 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)#

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

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

PyObject *PyArray_TypeObjectFromType(int type)#

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

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

请参阅函数 PyArray_MinScalarType ,这是在 NumPy 1.6.0 中引入的替代机制.

返回由 typenum 表示的标量类型以及 *arr 中的数组(如果 arr 不是 NULL ).假设数组的秩为0,并且仅在 typenum 表示有符号整数时使用.如果 arr 不是 NULL 并且第一个元素为负,则返回 NPY_INTNEG_SCALAR,否则返回 NPY_INTPOS_SCALAR.可能的返回值是 NPY_SCALARKIND 中的枚举值.

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

有关 NumPy 类型提升的详细信息,请参阅函数 PyArray_ResultType,该函数在 NumPy 1.6.0 中更新.

实现标量强制转换的规则.只有在函数返回非零值时,标量才会从thistype静默强制转换为neededtype.如果标量是 NPY_NOSCALAR ,则此函数等效于 PyArray_CanCastSafely .规则是相同KIND的标量可以强制转换为相同KIND的数组.此规则意味着高精度标量不会导致相同KIND的低精度数组被向上转换.

数据类型描述符#

警告

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

int PyArray_DescrCheck(PyObject *obj)#

如果 obj 是一个数据类型对象( PyArray_Descr* ),则评估为真.

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,则所有字节顺序都会被交换.其他有效的新字节顺序值是 NPY_NATIVENPY_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 参数设置为所需的大小.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结构的对象.

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``(除非其中一个 DTypes ``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 实现是结合的和交换的!(主要地,无符号和有符号整数不是.)

为了保证结果的一致性,DTypes 必须实现常见的 DType “传递性”.如果 A 提升 B 且 B 提升 C,那么 A 通常也必须提升 C;这里的”提升”意味着实现提升.(对于抽象 DTypes 有一些例外)

一般来说,只要最通用的数据类型严格大于或兼容所有其他数据类型,这种方法总是有效的.例如,将 float16 与其他任何浮点数、整数或无符号整数结合,结果仍然是一个浮点数.

PyArray_Descr *PyArray_GetDefaultDescr(const PyArray_DTypeMeta *DType)#

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

自定义数据类型#

在 2.0 版本加入.

这些函数允许在NumPy之外定义自定义的灵活数据类型.有关新DType系统的原理和设计的更多详细信息,请参阅 NEP 42 .有关示例DTypes,请参阅 numpy-user-dtypes 仓库 .另请参阅 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`(在调用 :c:func:`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的意义.这在 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#

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

NPY_DT_PyArray_ArrFuncs_setitem#

允许设置每个数据类型的 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 的非零函数,实现 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 实现的每种排序算法定义自定义的 argsort 实现.

宏和静态内联函数#

这些宏和静态内联函数是为了在使用 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)#

这是一个用于输出数组的默认转换器,提供给函数使用.如果 objPy_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 成员.:c:type:PyArray_Chunk 结构与 Python 的缓冲对象(通过其在 32 位平台上的 len 成员和在 64 位平台上的 ptr 成员)二进制兼容.返回时,base 成员设置为 obj*(如果 *obj 已经是指向另一个对象的缓冲对象,则设置为其 base).如果需要保留内存,请确保对 base 成员进行 INCREF.内存块由 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' 开头),:c:data:`NPY_HEAPSORT`(以 'h' 'H' 开头),:c:data:`NPY_MERGESORT`(以 'm' 'M' 开头)或 :c:data:`NPY_STABLESORT`(以 't' 'T' 开头).:c:data:`NPY_MERGESORTNPY_STABLESORT 互为别名,以保持向后兼容性,并可能根据数据类型引用几种稳定排序算法之一.

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

将 Python 字符串转换为 :c:data:`NPY_SEARCHLEFT`(以 ‘l’ 或 ‘L’ 开头),或 :c:data:`NPY_SEARCHRIGHT`(以 ‘r’ 或 ‘R’ 开头).

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

将 Python 字符串 ‘C’, ‘F’, ‘A’, 和 ‘K’ 转换为 NPY_ORDER 枚举 NPY_CORDER, NPY_FORTRANORDER, NPY_ANYORDER, 和 NPY_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_CASTING, 和 NPY_UNSAFE_CASTING.

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

将 Python 字符串 ‘clip’, ‘wrap’, 和 ‘raise’ 转换为 NPY_CLIPMODE 枚举 NPY_CLIP, NPY_WRAP, 和 NPY_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>

你也可以将最后两行放入一个扩展本地的头文件中,只要你确保在 #include 该文件之前定义了 NO_IMPORT_ARRAY.

在内部,这些 #defines 的工作原理如下:

  • 如果两者都没有定义,C-API 被声明为 static void**,因此它仅在编译单元中可见,该单元 #includes numpy/arrayobject.h.

  • 如果 PY_ARRAY_UNIQUE_SYMBOL 被 #定义,但 NO_IMPORT_ARRAY 未被定义,C-API 被声明为 void**,以便它也能被其他编译单元可见.

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

  • 每当 PY_ARRAY_UNIQUE_SYMBOL 被 #定义 时,它也会将持有 C-API 的变量名称(默认为 PyArray_API)更改为宏被 #定义 为的任何名称.

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

unsigned int PyArray_GetNDArrayCFeatureVersion(void)#

在 1.4.0 版本加入.

这仅仅返回值 NPY_FEATURE_VERSION . NPY_FEATURE_VERSION 在API改变时(例如,添加了一个函数)会改变.改变的值并不总是需要重新编译.

内存管理#

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,这个函数会清除标志,对 obj->base 进行 DECREF 并使其可写,然后将 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 线程可以在执行耗时计算时运行.这可以通过两组宏来实现.通常,如果在代码块中使用了一个组中的宏,则必须在同一代码块中使用所有宏.:c:data:NPY_ALLOW_THREADS 为真(定义为 1),除非设置了构建选项 -Ddisable-threadingtrue - 在这种情况下,:c:data:NPY_ALLOW_THREADS 为假(0).

NPY_ALLOW_THREADS#

第一组#

这个组用于调用可能需要一些时间但不会使用任何 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 的情况下,重新获取 GIL 非常有用.

void NPY_BEGIN_THREADS_THRESHOLDED(int loop_size)#

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

第二组#

这个组用于在释放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)#

返回 objdef__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.为了继续允许将其用作检查参数数量是否与ufuncs兼容的检查,这个宏现在是运行时依赖的.

备注

我们不鼓励任何未明确与检查已知 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)#

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

PyArray_MAX(a, b)#

返回 ab 的最大值.如果 (a) 或 (b) 是表达式,它们会被计算两次.

PyArray_MIN(a, b)#

返回 ab 的最小值.如果 (a) 或 (b) 是表达式,它们会被计算两次.

void PyArray_DiscardWritebackIfCopy(PyArrayObject *obj)#

如果 obj->flags 具有 NPY_ARRAY_WRITEBACKIFCOPY,此函数会清除标志,对 obj->base 进行 DECREF 并使其可写,并将 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_CORDERNPY_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#

在 1.6 版本加入.

一个枚举类型,指示数据转换的宽容度应如何.这是在 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#

允许任何转换,无论可能发生何种数据丢失.