Python Types and C-Structures

原文:https://docs.scipy.org/doc/numpy/reference/c-api.types-and-structures.html

译者:飞龙 UsyiyiCN

校对:(虚位以待)

在C代码中定义了几种新类型。其中大部分都可以从Python访问,但有些不会暴露,由于他们有限的使用。每个新的Python类型都有一个关联的PyObject *,其内部结构包含一个指向“方法表”的指针,在Python中行为。当你收到一个Python对象到C代码,你总是得到一个PyObject结构的指针。因为PyObject结构非常通用,只定义了PyObject_HEAD,它本身并不是很有趣。但是,不同的对象在PyObject_HEAD之后包含更多细节(但是你必须转换为正确的类型来访问它们 - 或者使用访问器函数或宏)。

New Python Types Defined

Python类型是Python中的C类的函数等价物。通过构造一个新的Python类型,你可以为Python提供一个新的对象。ndarray对象是在C中定义的新类型的示例。新类型在C中通过两个基本步骤来定义:

  1. 创建与PyObject结构本身二进制兼容的C结构(通常命名为Py{Name}Object),但保存该特定对象所需的附加信息;
  2. 使用指向实现所期望的类型行为的函数的指针来填充PyTypeObject表(由PyObject结构的ob_type成员指向)。

而不是为Python类定义行为的特殊方法名称,有“函数表”指向实现所需结果的函数。自Python 2.2以来,PyTypeObject本身已经变成动态的,允许C类型可以从C中的其他C类型“子类型化”,并在Python中进行子类化。子类型从其父类继承属性和方法。

有两种主要的新类型:ndarray(PyArray_Type)和ufunc(PyUFunc_Type)。其他类型发挥了支持作用:PyArrayIter_TypePyArrayMultiIter_TypePyArrayDescr_TypePyArrayIter_Type是用于ndarray(获取平面属性时返回的对象)的平面迭代器的类型。PyArrayMultiIter_Type是调用broadcast()时返回的对象的类型。它处理迭代和广播通过嵌套序列的集合。此外,PyArrayDescr_Type是数据类型描述符类型,其实例描述数据。最后,有21个新的标量数组类型是对应于数组可用的每个基本数据类型的新的Python标量。另外10种其他类型是占位符,允许数组标量适合实际Python类型的层次结构。

PyArray_Type

PyArrayObject

PyArrayObject C结构包含数组的所有必需信息。ndarray(及其子类)的所有实例都将具有此结构。为了将来兼容性,这些结构成员通常应使用提供的宏访问。如果你需要一个更短的名字,那么你可以使用NPY_AO,它被定义为等同于PyArrayObject

typedef struct PyArrayObject {
    PyObject_HEAD
    char *data;
    int nd;
    npy_intp *dimensions;
    npy_intp *strides;
    PyObject *base;
    PyArray_Descr *descr;
    int flags;
    PyObject *weakreflist;
} PyArrayObject;
char *PyArrayObject.data

指向数组的第一个元素的指针。这个指针可以(通常应该)重写为数组的数据类型。

int PyArrayObject.nd

一个整数,提供此数组的维数。当nd为0时,数组有时称为秩0数组。这样的数组具有未定义的尺寸和步幅,并且不能被访问。NPY_MAXDIMS是任何数组的最大维数。

npy_intp PyArrayObject.dimensions

整数的数组,只要nd \geq 1,就提供每个维度的形状。整数总是足够大以在平台上保存指针,因此维度大小仅受内存限制。

npy_intp *PyArrayObject.strides

整数数组,为每个维度提供必须跳过以获取该维度中下一个元素的字节数。

PyObject *PyArrayObject.base

此成员用于保存指向与此数组相关的另一个Python对象的指针。有两种使用情况:1)如果这个数组不拥有自己的内存,那么base指向拥有它的Python对象(也许是另一个数组对象),2)如果这个数组有NPY_ARRAY_UPDATEIFCOPY标志集,则此数组是“错误”数组的工作副本。一旦删除此数组,由base指向的数组将使用此数组的内容进行更新。

PyArray_Descr *PyArrayObject.descr

指向数据类型描述符对象的指针(见下文)。数据类型描述符对象是新的内置类型的实例,其允许对存储器的通用描述。每个支持的数据类型都有一个描述符结构。这个描述符结构包含有关类型的有用信息以及指向实现特定功能的函数指针表的指针。

int PyArrayObject.flags

指示如何解释由数据指向的存储器的标志。Possible flags are NPY_ARRAY_C_CONTIGUOUS, NPY_ARRAY_F_CONTIGUOUS, NPY_ARRAY_OWNDATA, NPY_ARRAY_ALIGNED, NPY_ARRAY_WRITEABLE, and NPY_ARRAY_UPDATEIFCOPY.

PyObject *PyArrayObject.weakreflist

此成员允许数组对象具有弱引用(使用weakref模块)。

PyArrayDescr_Type

PyArray_Descr

位于PyArrayDescr_Type中心的PyArray_Descr结构的格式为

typedef struct {
    PyObject_HEAD
    PyTypeObject *typeobj;
    char kind;
    char type;
    char byteorder;
    char unused;
    int flags;
    int type_num;
    int elsize;
    int alignment;
    PyArray_ArrayDescr *subarray;
    PyObject *fields;
    PyArray_ArrFuncs *f;
} PyArray_Descr;
PyTypeObject *PyArray_Descr.typeobj

指向类型对象的指针,该对象是此数组元素的相应Python类型。对于内置类型,这指向相应的数组标量。对于用户定义的类型,这应该指向一个用户定义的类型对象。此类型对象可以继承数组标量,也可以不继承。如果它不继承数组标量,则应在flags成员中设置NPY_USE_GETITEMNPY_USE_SETITEM标志。

char PyArray_Descr.kind

指示数组种类的字符代码(使用数组接口typestring符号)。A'b'表示布尔值,a'i表示有符号整数,'u'表示无符号整数,'f'表示浮点,'c'表示复数浮点,'S'表示8位字符串,'U '表示32位/字符Unicode字符串,'V'表示任意。

char PyArray_Descr.type

指示数据类型的传统字符代码。

char PyArray_Descr.byteorder

表示字节顺序的字符:'>'(big-endian),'所有内置数据类型都具有字节序“=”。

int PyArray_Descr.flags

数据类型位标志,用于确定数据类型是否显示对象数组行为。此成员中的每个位都是一个标志,命名为:

PyDataType_FLAGCHK(PyArray_Descr *dtype, int flags)

如果为数据类型对象设置了所有给定的标志,则返回true。

PyDataType_REFCHK(PyArray_Descr *dtype)

等效于PyDataType_FLAGCHKdtypeNPY_ITEM_REFCOUNT)。

int PyArray_Descr.type_num

唯一标识数据类型的数字。对于新的数据类型,此数字在注册数据类型时分配。

int PyArray_Descr.elsize

对于始终具有相同大小(例如长)的数据类型,这将保存数据类型的大小。对于不同数组可以有不同元素大小的灵活数据类型,这应该是0。

int PyArray_Descr.alignment

为此数据类型提供对齐信息的数字。具体来说,它显示了从2元素结构(其第一个元素是char)开始多远,编译器放置一个这种类型的项:offsetof(struct {char c; type v;}, v) / t2>

PyArray_ArrayDescr *PyArray_Descr.subarray

如果这是非NULL,则该数据类型描述符是另一数据类型描述符的C样式连续数组。换句话说,该描述符描述的每个元素实际上是一些其他基本描述符的数组。这对于另一个数据类型描述符中的字段是最有用的。如果这是非NULL(基础描述符的fields成员可以是非NULL),则fields成员应为NULLPyArray_ArrayDescr结构是使用定义的

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

这个结构的元素是:

PyArray_Descr *PyArray_ArrayDescr.base

base-type的数据类型描述符对象。

PyObject *PyArray_ArrayDescr.shape

子数组的形状(总是C型连续)作为Python元组。

PyObject *PyArray_Descr.fields

如果这是非NULL,那么这个数据类型描述符具有由Python字典描述的字段,其键是名称(以及标题,如果给出的话),并且其值是描述字段的元组。回想一下,数据类型描述符总是描述固定长度的字节集合。字段是该总长度固定长度集合的命名子区域。字段由由另一个数据类型描述符和字节偏移组成的元组描述。可选地,元组可以包含通常是Python字符串的标题。这些元组被放在这个字典键入的名称(以及标题,如果给定)。

PyArray_ArrFuncs *PyArray_Descr.f

指向包含类型需要实现内部要素的函数的结构的指针。这些函数与后面描述的通用函数(ufunc)不同。他们的签名可以任意变化。

PyArray_ArrFuncs

实现内部功能的功能。不是所有这些函数指针必须为给定类型定义。所需成员为nonzerocopyswapcopyswapnsetitemgetitem cast这些假设为非NULLNULL条目会导致程序崩溃。其他函数可以是NULL,这将意味着该数据类型的减少的功能。(此外,如果在注册用户定义的数据类型时NULL,则非零函数将使用默认函数填充)。

typedef struct {
    PyArray_VectorUnaryFunc *cast[NPY_NTYPES];
    PyArray_GetItemFunc *getitem;
    PyArray_SetItemFunc *setitem;
    PyArray_CopySwapNFunc *copyswapn;
    PyArray_CopySwapFunc *copyswap;
    PyArray_CompareFunc *compare;
    PyArray_ArgFunc *argmax;
    PyArray_DotFunc *dotfunc;
    PyArray_ScanFunc *scanfunc;
    PyArray_FromStrFunc *fromstr;
    PyArray_NonzeroFunc *nonzero;
    PyArray_FillFunc *fill;
    PyArray_FillWithScalarFunc *fillwithscalar;
    PyArray_SortFunc *sort[NPY_NSORTS];
    PyArray_ArgSortFunc *argsort[NPY_NSORTS];
    PyObject *castdict;
    PyArray_ScalarKindFunc *scalarkind;
    int **cancastscalarkindto;
    int *cancastto;
    PyArray_FastClipFunc *fastclip;
    PyArray_FastPutmaskFunc *fastputmask;
    PyArray_FastTakeFunc *fasttake;
    PyArray_ArgFunc *argmin;
} PyArray_ArrFuncs;

行为段的概念用于函数指针的描述。行为段是对齐的,并且以数据类型的本机机器字节顺序。nonzerocopyswapcopyswapngetitemsetitem必须)处理误操作的数组。其他功能需要行为存储器段。

void cast(void *from, void *to, npy_intp n, void *fromarr, void *toarr)

一个数组的函数指针,从当前类型转换为所有其他内建类型。每个函数将指向的连续,对齐和未交换缓冲区从转换为指向的连续,对齐和未交换的缓冲区到给出的项目数量由n,参数fromarrtoarr被解释为PyArrayObjects,用于灵活数组获取itemsize信息。

PyObject *getitem(void *data, void *arr)

指向从数据指向的数组对象arr的单个元素返回标准Python对象的函数的指针。此功能必须能够正确处理“错误”(未对齐和/或交换)数组。

int setitem(PyObject *item, void *data, void *arr)

指向在数据指向的位置将Python对象设置为数组arr的函数的指针。此函数处理“misbehaved”数组。如果成功,则返回零,否则返回负数(并设置Python错误)。

void copyswapn(void *dest, npy_intp dstride, void *src, npy_intp sstride, npy_intp n, int swap, void *arr)
void copyswap(void *dest, void *src, int swap, void *arr)

这些成员都是指向从srcdest交换(如果指示)复制数据的函数的指针。arr的值仅用于灵活(NPY_STRINGNPY_UNICODENPY_VOID)数组(并且从arr->descr->elsize)。第二个函数复制单个值,而第一个函数使用提供的步长循环n个值。这些函数可以处理错误的src数据。如果src为NULL,则不执行复制。如果swap为0,则不会发生字节交换。假设destsrc不重叠。如果它们重叠,则首先使用memmove(...),然后使用NULL值src跟随copyswap(n)

int compare(const void* d1, const void* d2, void* arr)

指向比较由d1d2指向的数组的两个元素arr的函数的指针。此函数需要行为(对齐和不交换)数组。The return value is 1 if * d1 > * d2, 0 if * d1 == * d2, and -1 if * d1 < * d2. 数组对象arr用于检索灵活数组的项目大小和字段信息。

int argmax(void* data, npy_intp n, npy_intp* max_ind, void* arr)

指向arr中从data指向的元素开始检索n中最大元素的索引的函数的指针。这个函数要求内存段是连续的和行为的。返回值始终为0。最大元素的索引在max_ind中返回。

void dotfunc(void* ip1, npy_intp is1, void* ip2, npy_intp is2, void* op, npy_intp n, void* arr)

指向一个将两个n长序列相乘的函数的指针,将它们添加,并将结果放在arrop两个序列的开始由ip1ip2指向。要到达每个序列中的下一个元素,需要分别跳过is1is2 字节此函数需要行为(但不一定是连续的)内存。

int scanfunc(FILE* fd, void* ip, void* sep, void* arr)

指向一个函数的指针,该函数将相应类型的一个元素从文件描述符fd扫描(scanf style)到ip指向的数组内存。数组被假定为行为。如果sep不为NULL,则在返回之前还会从文件中扫描分隔符字符串。最后一个参数arr是要扫描的数组。如果扫描成功,返回0。负数表示发生错误:-1表示在扫描分隔符字符串之前到达文件结尾,-4表示在扫描元素之前到达文件结尾,-3表示该元素可以不能从格式字符串中解释。需要一个behaved数组。

int fromstr(char* str, void* ip, char** endptr, void* arr)

指向一个函数的指针,该函数将由str指向的字符串转换为相应类型的一个元素,并将它放在ip指向的内存位置。转换完成后,*endptr指向字符串的其余部分。最后一个参数arr是ip指向的数组(可变大小数据类型所需)。成功返回0或失败返回-1。需要一个behaved数组。

Bool nonzero(void* data, void* arr)

指向data指向的arr项目为非零的函数的指针。这个函数可以处理不正确的数组。

void fill(void* data, npy_intp length, void* arr)

指向一个函数的指针,该函数用数据填充给定长度的连续数组。数组的前两个元素必须已填充。从这两个值,将计算增量,并且将通过重复地添加该计算的增量来计算从项3到结束的值。数据缓冲器必须是良好的。

void fillwithscalar(void* buffer, npy_intp length, void* value, void* arr)

指向一个函数的指针,该函数使用给定地址的单个标量value填充给定length的连续buffer最后一个参数是获取可变长度数组的itemsize所需的数组。

int sort(void* start, npy_intp length, void* arr)

指向特定排序算法的函数指针的数组。使用键(到目前为止定义了NPY_QUICKSORTNPY_HEAPSORTNPY_MERGESORT)获得特定的排序算法。这些排序是在现场完成的,假设连续和对齐的数据。

int argsort(void* start, npy_intp* result, npy_intp length, void *arr)

用于此数据类型的排序算法的函数指针数组。可以使用与sort相同的排序算法。产生排序的索引在result(其必须用索引0到length-1)中返回。

PyObject *castdict

NULL或包含用户定义数据类型的低级别转换函数的字典。每个函数包裹在PyCObject *中,并由数据类型数字键入。

NPY_SCALARKIND scalarkind(PyArrayObject* arr)

用于确定如何解释此类型的标量的函数。参数是NULL或包含数据的0维数组(如果需要确定标量的种类)。返回值的类型必须为NPY_SCALARKIND

int **cancastscalarkindto

NULL或数组NPY_NSCALARKINDS指针。这些指针应该是NULL或指向整数数组(由NPY_NOTYPE终止)的指针,指示指定类型的此数据类型的标量的数据类型可以安全地(这通常意味着不丧失精度)。

int *cancastto

NULL或整数数组(由NPY_NOTYPE终止)表示此数据类型可以安全转换的数据类型(这通常意味着不会丢失精度)。

void fastclip(void *in, npy_intp n_in, void *min, void *max, void *out)

A function that reads n_in items from in, and writes to out the read value if it is within the limits pointed to by min and max, or the corresponding limit if outside. 存储器段必须是连续的并且表现的,并且minmax可以是NULL,但不能两者。

void fastputmask(void *in, void *mask, npy_intp n_in, void *values, npy_intp nv)

A function that takes a pointer in to an array of n_in items, a pointer mask to an array of n_in boolean values, and a pointer vals to an array of nv items. Items from vals are copied into in wherever the value in mask is non-zero, tiling vals as needed if nv < n_in. 所有数组必须是连续的和行为的。

void fasttake(void *dest, void *src, npy_intp *indarray, npy_intp nindarray, npy_intp n_outer, npy_intp m_middle, npy_intp nelem, NPY_CLIPMODE clipmode)

A function that takes a pointer src to a C contiguous, behaved segment, interpreted as a 3-dimensional array of shape (n_outer, nindarray, nelem), a pointer indarray to a contiguous, behaved segment of m_middle integer indices, and a pointer dest to a C contiguous, behaved segment, interpreted as a 3-dimensional array of shape (n_outer, m_middle, nelem). indarray中的索引用于沿着第二维度索引src,并将nelem项目的相应块拷贝到destclipmode(可以取值NPY_RAISENPY_WRAPNPY_CLIP)决定索引小于0或大于nindarray将被处理。

int argmin(void* data, npy_intp n, npy_intp* min_ind, void* arr)

指向arrdata指向的元素开始检索n中最小元素的索引的函数的指针。这个函数要求内存段是连续的和行为的。返回值始终为0。最小元素的索引在min_ind中返回。

PyArray_Type typeobject实现Python对象的许多功能,包括tp_as_number,tp_as_sequence,tp_as_mapping和tp_as_buffer接口。丰富比较(tp_richcompare)也与方法(tp_methods)和属性(tp_getset)的新样式属性查找一起使用。PyArray_Type也可以是子类型。

小费

tp_as_number方法使用通用方法调用已注册的任何函数来处理操作。函数PyNumeric_SetOps(..)可用于注册函数以处理特定的数学运算(对于所有数组)。当导入umath模块时,它将所有数组的数字操作设置为相应的ufuncs。tp_str和tp_repr方法也可以使用PyString_SetStringFunction(...)来改变。

PyUFunc_Type

PyUFuncObject

ufunc的核心是PyUFuncObject,其中包含调用执行实际工作的底层C代码循环所需的所有信息。它具有以下结构:

typedef struct {
    PyObject_HEAD
    int nin;
    int nout;
    int nargs;
    int identity;
    PyUFuncGenericFunction *functions;
    void **data;
    int ntypes;
    int reserved1;
    const char *name;
    char *types;
    const char *doc;
    void *ptr;
    PyObject *obj;
    PyObject *userloops;
    npy_uint32 *op_flags;
    npy_uint32 *iter_flags;
} PyUFuncObject;
int PyUFuncObject.nin

输入参数的数量。

int PyUFuncObject.nout

输出参数的数量。

int PyUFuncObject.nargs

参数的总数(nin + nout)。此值必须小于NPY_MAXARGS

int PyUFuncObject.identity

PyUFunc_OnePyUFunc_ZeroPyUFunc_NonePyUFunc_AllOnes以指示此操作的身份。它只用于对空数组的reduce类调用。

void PyUFuncObject.functions(char ** args,npy_intp * dims,
npy_intp * steps,void * extradata)

函数指针的数组 - 一个用于ufunc支持的每个数据类型。这是被调用来实现底层函数dims [0]次的向量循环。第一个参数argsnargs指向行为内存的指针的数组。指向输入参数数据的指针是第一个,后跟指向输出参数数据的指针。必须跳过多少字节才能到达序列中的下一个元素,由步骤数组中的相应条目指定。最后一个参数允许循环接收额外的信息。这是通常使用的,使得单个通用向量循环可以用于多个函数。在这种情况下,要调用的实际标量函数以extradata形式传递。此函数指针数组的大小为ntypes。

void **PyUFuncObject.data

如果不需要额外数据,则将额外数据传递到1-d向量循环或NULL此C阵列必须与函数数组相同大小(,即 ntypes)。如果不需要extra_data,则使用NULL对UFunc的几个C-API调用只是1-d向量循环,它使用这个额外的数据来接收指向实际调用的函数的指针。

int PyUFuncObject.ntypes

ufunc支持的数据类型数。此数字指定(内置数据类型的)多少个不同的1-d循环可用。

char *PyUFuncObject.name

ufunc的字符串名称。这被动态地用于构建ufuncs的__doc__属性。

char *PyUFuncObject.types

nargs \times ntypes 8位类型数的数组,其包含每种受支持(内置)数据类型的函数的类型签名。对于每个ntypes函数,此数组中相应的类型数集合显示如何在1-d向量循环中解释args参数。这些类型数字不必是相同的类型,并且支持混合型ufunc。

char *PyUFuncObject.doc

ufunc的文档。不应该包含函数签名,因为这是在检索__doc__时动态生成的。

void *PyUFuncObject.ptr

任何动态分配的内存。目前,这用于从一个python函数创建的动态ufuncs,为类型,数据和名称成员存储空间。

PyObject *PyUFuncObject.obj

对于从python函数动态创建的ufuncs,此成员持有对底层Python函数的引用。

PyObject *PyUFuncObject.userloops

用户定义的1-d向量循环(存储为CObject ptrs)的字典。用户可以为任何用户定义的类型注册循环。它按类型号检索。用户定义的类型数字始终大于NPY_USERDEF

npy_uint32 PyUFuncObject.op_flags

覆盖每个ufunc操作数的默认操作数标志。

npy_uint32 PyUFuncObject.iter_flags

覆盖ufunc的默认nditer标志。

PyArrayIter_Type

PyArrayIterObject

对应于PyArrayIter_Type的对象的C结构是PyArrayIterObjectPyArrayIterObject用于跟踪指向N维数组的指针。它包含用于快速穿过数组的相关信息。指针可以以三种基本方式进行调整:1)以C形连续方式前进到数组中的“下一个”位置,2)前进到数组中的任意N维坐标,以及3)前进到到数组的任意一维索引。在这些计算中使用PyArrayIterObject结构的成员。迭代器对象保留自己的维度并跨越数组的信息。这可以根据“广播”的需要进行调整,或者仅循环特定尺寸。

typedef struct {
    PyObject_HEAD
    int   nd_m1;
    npy_intp  index;
    npy_intp  size;
    npy_intp  coordinates[NPY_MAXDIMS];
    npy_intp  dims_m1[NPY_MAXDIMS];
    npy_intp  strides[NPY_MAXDIMS];
    npy_intp  backstrides[NPY_MAXDIMS];
    npy_intp  factors[NPY_MAXDIMS];
    PyArrayObject *ao;
    char  *dataptr;
    Bool  contiguous;
} PyArrayIterObject;
int PyArrayIterObject.nd_m1

N-1其中N是底层数组中的维数。

npy_intp PyArrayIterObject.index

到数组的当前1-d索引。

npy_intp PyArrayIterObject.size

底层数组的总大小。

npy_intp *PyArrayIterObject.coordinates

到数组的N维索引。

npy_intp *PyArrayIterObject.dims_m1

数组的大小在每个维度中减1。

npy_intp *PyArrayIterObject.strides

数组的步幅。需要多少字节来跳转到每个维度中的下一个元素。

npy_intp *PyArrayIterObject.backstrides

需要多少字节从维度的结尾跳回到它的开始。注意,背面[k] == strides [k] * dims_m1 [k ],但它在此处存储为优化。

npy_intp *PyArrayIterObject.factors

该数组用于从1-d索引计算N-d索引。它包含所需的尺寸产品。

PyArrayObject *PyArrayIterObject.ao

指向底层的ndarray的指针这个迭代器被创建来表示。

char *PyArrayIterObject.dataptr

此成员指向由索引指示的ndarray中的元素。

Bool PyArrayIterObject.contiguous

如果基础数组为NPY_ARRAY_C_CONTIGUOUS,则此标志为真。如果可能,它用于简化计算。

如何在C级使用数组迭代器将在后面的章节中详细解释。通常,你不需要关心迭代器对象的内部结构,只需使用宏PyArray_ITER_NEXT(it),PyArray_ITER_GOTO it,dest)或PyArray_ITER_GOTO1D(it,index)。所有这些宏都需要参数itPyArrayIterObject *

PyArrayMultiIter_Type

PyArrayMultiIterObject
typedef struct {
    PyObject_HEAD
    int numiter;
    npy_intp size;
    npy_intp index;
    int nd;
    npy_intp dimensions[NPY_MAXDIMS];
    PyArrayIterObject *iters[NPY_MAXDIMS];
} PyArrayMultiIterObject;
int PyArrayMultiIterObject.numiter

需要广播到相同形状的数组的数量。

npy_intp PyArrayMultiIterObject.size

总广播尺寸。

npy_intp PyArrayMultiIterObject.index

当前(1-d)索引到广播结果中。

int PyArrayMultiIterObject.nd

广播结果中的维度数。

npy_intp *PyArrayMultiIterObject.dimensions

广播结果的形状(仅使用nd个时隙)。

PyArrayIterObject **PyArrayMultiIterObject.iters

一个迭代器对象的数组,它保存要一起广播的数组的迭代器。返回时,迭代器被调整用于广播。

PyArrayNeighborhoodIter_Type

PyArrayNeighborhoodIterObject

对应于PyArrayNeighborhoodIter_Type的对象的C结构是PyArrayNeighborhoodIterObject

PyArrayFlags_Type

ScalarArrayTypes

对于可以出现在数组中的每个不同的内置数据类型,都有一个Python类型。大多数这些类型是C中相应数据类型的简单包装器。这些类型的C名称是Py{TYPE}ArrType_Type其中{TYPE}可以

Bool, Byte, Short, Int, Long, LongLong, UByte, UShort, UInt, ULong, ULongLong, Half, Float, Double, LongDouble, CFloat, CDouble, CLongDouble, String, Unicode, Void, and Object.

这些类型名称是C-API的一部分,因此可以在扩展C代码中创建。还有一个PyIntpArrType_TypePyUIntpArrType_Type,它们是可以在平台上保存指针的整数类型之一的简单替换。这些标量对象的结构不暴露给C代码。函数PyArray_ScalarAsCtype(..)可用于从数组标量提取C类型值,函数PyArray_Scalar(...)可用于构造数组标量从C值。

Other C-Structures

发现一些新的C结构在NumPy的开发中是有用的。这些C结构用在至少一个C-API调用中,因此在这里被记录。这些结构被定义的主要原因是使得使用Python ParseTuple C-API将Python对象转换为有用的C对象变得容易。

PyArray_Dims

PyArray_Dims

当想要解释形状和/或步幅信息时,这种结构是非常有用的。结构是:

typedef struct {
    npy_intp *ptr;
    int len;
} PyArray_Dims;

这个结构的成员是

npy_intp *PyArray_Dims.ptr

指向通常表示数组形状或数组步长的(npy_intp)整数列表的指针。

int PyArray_Dims.len

整数列表的长度。假定安全地访问ptr [0]到ptr [len-1]。

PyArray_Chunk

PyArray_Chunk

这相当于Python中的缓冲区对象结构,直到ptr成员。在32位平台上(,即 if NPY_SIZEOF_INT == NPY_SIZEOF_INTP),len成员还与缓冲区对象的等效成员匹配。表示通用的单段内存块是有用的。

typedef struct {
    PyObject_HEAD
    PyObject *base;
    void *ptr;
    npy_intp len;
    int flags;
} PyArray_Chunk;

会员是

PyObject *PyArray_Chunk.base

Python对象这个内存块来自。需要,以便内存可以正确地解决。

void *PyArray_Chunk.ptr

指向单段内存块的开始的指针。

npy_intp PyArray_Chunk.len

段的长度(以字节为单位)。

int PyArray_Chunk.flags

应用于解释内存的任何数据标志(例如 NPY_ARRAY_WRITEABLE)。

PyArrayInterface

也可以看看

The Array Interface

PyArrayInterface

定义PyArrayInterface结构,使NumPy和其他扩展模块可以使用快速数组接口协议。支持快速数组接口协议的对象的__array_struct__方法应返回包含指向PyArrayInterface结构的指针的PyCObject的数组。创建新数组后,属性应为DECREF'd,它将释放PyArrayInterface结构。请记住INCREF对象(检索其__array_struct__属性),并将新PyArrayObject的基础成员指向同一个对象。这样,数组的内存将被正确管理。

typedef struct {
    int two;
    int nd;
    char typekind;
    int itemsize;
    int flags;
    npy_intp *shape;
    npy_intp *strides;
    void *data;
    PyObject *descr;
} PyArrayInterface;
int PyArrayInterface.two

整数2作为健全性检查。

int PyArrayInterface.nd

数组中的维数。

char PyArrayInterface.typekind

根据typestring约定用't' - >位字段,'b' - >布尔,'i' - >有符号整数,'u' - >无符号整数,'f' - >浮点,'c' - >复杂浮点,'O' - >对象,'S' - >(字节 - )字符串,'U' - > unicode,'V'

int PyArrayInterface.itemsize

数组中每个项目所需的字节数。

int PyArrayInterface.flags

NPY_ARRAY_C_CONTIGUOUS(1),NPY_ARRAY_F_CONTIGUOUS(2),NPY_ARRAY_ALIGNED(0x100),NPY_ARRAY_NOTSWAPPED )或NPY_ARRAY_WRITEABLE(0x400)来表示数据。NPY_ARRAY_ALIGNEDNPY_ARRAY_C_CONTIGUOUSNPY_ARRAY_F_CONTIGUOUS标志实际上可以从其他参数确定。还可以设置标志NPY_ARR_HAS_DESCR(0x800)以指示使用版本3数组接口的对象存在结构的descr成员(它将被消耗版本2的数组接口的对象忽略) )。

npy_intp *PyArrayInterface.shape

包含每个维中数组大小的数组。

npy_intp *PyArrayInterface.strides

包含要跳到每个维度中的下一个元素的字节数的数组。

void *PyArrayInterface.data

指针数组的第一个元素。

PyObject *PyArrayInterface.descr

更详细地描述数据类型的Python对象(与__array_interface__中的descr键相同)。如果typekinditemize提供足够的信息,则可以NULL除非标志中的ARR_HAS_DESCR标志为开,因此也会忽略此字段。

Internally used structures

在内部,代码使用一些额外的Python对象主要用于内存管理。这些类型不能直接从Python访问,并且不暴露给C-API。它们在这里只是为了完整性和帮助理解代码。

PyUFuncLoopObject

用于包含循环所需信息的C结构的松散包装器。如果你想了解ufunc循环代码,这是有用的。PyUFuncLoopObject是关联的C结构。它在ufuncobject.h头中定义。

PyUFuncReduceObject

C结构的松散包装,包含ufuncs的reduce类方法所需的信息。如果你想要理解reduce,accumulate和reduce-at代码,这很有用。PyUFuncReduceObject是关联的C结构。它在ufuncobject.h头中定义。

PyUFunc_Loop1d

包含为用户定义的数据类型的每个定义的签名定义用于ufunc的1-d循环所需的信息的C结构的简单链接列表。