原文:https://docs.scipy.org/doc/numpy/reference/c-api.types-and-structures.html
校对:(虚位以待)
在C代码中定义了几种新类型。其中大部分都可以从Python访问,但有些不会暴露,由于他们有限的使用。每个新的Python类型都有一个关联的PyObject *,其内部结构包含一个指向“方法表”的指针,在Python中行为。当你收到一个Python对象到C代码,你总是得到一个PyObject结构的指针。因为PyObject结构非常通用,只定义了PyObject_HEAD,它本身并不是很有趣。但是,不同的对象在PyObject_HEAD之后包含更多细节(但是你必须转换为正确的类型来访问它们 - 或者使用访问器函数或宏)。
Python类型是Python中的C类的函数等价物。通过构造一个新的Python类型,你可以为Python提供一个新的对象。ndarray对象是在C中定义的新类型的示例。新类型在C中通过两个基本步骤来定义:
PyObject结构本身二进制兼容的C结构(通常命名为Py{Name}Object),但保存该特定对象所需的附加信息;PyTypeObject表(由PyObject结构的ob_type成员指向)。而不是为Python类定义行为的特殊方法名称,有“函数表”指向实现所需结果的函数。自Python 2.2以来,PyTypeObject本身已经变成动态的,允许C类型可以从C中的其他C类型“子类型化”,并在Python中进行子类化。子类型从其父类继承属性和方法。
有两种主要的新类型:ndarray(PyArray_Type)和ufunc(PyUFunc_Type)。其他类型发挥了支持作用:PyArrayIter_Type,PyArrayMultiIter_Type和PyArrayDescr_Type。PyArrayIter_Type是用于ndarray(获取平面属性时返回的对象)的平面迭代器的类型。PyArrayMultiIter_Type是调用broadcast()时返回的对象的类型。它处理迭代和广播通过嵌套序列的集合。此外,PyArrayDescr_Type是数据类型描述符类型,其实例描述数据。最后,有21个新的标量数组类型是对应于数组可用的每个基本数据类型的新的Python标量。另外10种其他类型是占位符,允许数组标量适合实际Python类型的层次结构。
PyArrayObjectPyArrayObject 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;
PyArrayObject.data指向数组的第一个元素的指针。这个指针可以(通常应该)重写为数组的数据类型。
PyArrayObject.nd一个整数,提供此数组的维数。当nd为0时,数组有时称为秩0数组。这样的数组具有未定义的尺寸和步幅,并且不能被访问。NPY_MAXDIMS是任何数组的最大维数。
PyArrayObject.dimensions整数的数组,只要nd
1,就提供每个维度的形状。整数总是足够大以在平台上保存指针,因此维度大小仅受内存限制。
PyArrayObject.strides整数数组,为每个维度提供必须跳过以获取该维度中下一个元素的字节数。
PyArrayObject.base此成员用于保存指向与此数组相关的另一个Python对象的指针。有两种使用情况:1)如果这个数组不拥有自己的内存,那么base指向拥有它的Python对象(也许是另一个数组对象),2)如果这个数组有NPY_ARRAY_UPDATEIFCOPY标志集,则此数组是“错误”数组的工作副本。一旦删除此数组,由base指向的数组将使用此数组的内容进行更新。
PyArrayObject.descr指向数据类型描述符对象的指针(见下文)。数据类型描述符对象是新的内置类型的实例,其允许对存储器的通用描述。每个支持的数据类型都有一个描述符结构。这个描述符结构包含有关类型的有用信息以及指向实现特定功能的函数指针表的指针。
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.
PyArrayObject.weakreflist此成员允许数组对象具有弱引用(使用weakref模块)。
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;
PyArray_Descr.typeobj指向类型对象的指针,该对象是此数组元素的相应Python类型。对于内置类型,这指向相应的数组标量。对于用户定义的类型,这应该指向一个用户定义的类型对象。此类型对象可以继承数组标量,也可以不继承。如果它不继承数组标量,则应在flags成员中设置NPY_USE_GETITEM和NPY_USE_SETITEM标志。
PyArray_Descr.kind指示数组种类的字符代码(使用数组接口typestring符号)。A'b'表示布尔值,a'i表示有符号整数,'u'表示无符号整数,'f'表示浮点,'c'表示复数浮点,'S'表示8位字符串,'U '表示32位/字符Unicode字符串,'V'表示任意。
PyArray_Descr.type指示数据类型的传统字符代码。
PyArray_Descr.byteorder表示字节顺序的字符:'>'(big-endian),'所有内置数据类型都具有字节序“=”。
PyArray_Descr.flags数据类型位标志,用于确定数据类型是否显示对象数组行为。此成员中的每个位都是一个标志,命名为:
PyDataType_FLAGCHK(PyArray_Descr *dtype, int flags)如果为数据类型对象设置了所有给定的标志,则返回true。
PyDataType_REFCHK(PyArray_Descr *dtype)等效于PyDataType_FLAGCHK(dtype,NPY_ITEM_REFCOUNT)。
PyArray_Descr.type_num唯一标识数据类型的数字。对于新的数据类型,此数字在注册数据类型时分配。
PyArray_Descr.elsize对于始终具有相同大小(例如长)的数据类型,这将保存数据类型的大小。对于不同数组可以有不同元素大小的灵活数据类型,这应该是0。
PyArray_Descr.alignment为此数据类型提供对齐信息的数字。具体来说,它显示了从2元素结构(其第一个元素是char)开始多远,编译器放置一个这种类型的项:offsetof(struct {char c; type v;}, v) / t2>
PyArray_Descr.subarray如果这是非NULL,则该数据类型描述符是另一数据类型描述符的C样式连续数组。换句话说,该描述符描述的每个元素实际上是一些其他基本描述符的数组。这对于另一个数据类型描述符中的字段是最有用的。如果这是非NULL(基础描述符的fields成员可以是非NULL),则fields成员应为NULL。PyArray_ArrayDescr结构是使用定义的
typedef struct {
PyArray_Descr *base;
PyObject *shape;
} PyArray_ArrayDescr;
这个结构的元素是:
PyArray_ArrayDescr.basebase-type的数据类型描述符对象。
PyArray_ArrayDescr.shape子数组的形状(总是C型连续)作为Python元组。
PyArray_Descr.fields如果这是非NULL,那么这个数据类型描述符具有由Python字典描述的字段,其键是名称(以及标题,如果给出的话),并且其值是描述字段的元组。回想一下,数据类型描述符总是描述固定长度的字节集合。字段是该总长度固定长度集合的命名子区域。字段由由另一个数据类型描述符和字节偏移组成的元组描述。可选地,元组可以包含通常是Python字符串的标题。这些元组被放在这个字典键入的名称(以及标题,如果给定)。
PyArray_Descr.f指向包含类型需要实现内部要素的函数的结构的指针。这些函数与后面描述的通用函数(ufunc)不同。他们的签名可以任意变化。
PyArray_ArrFuncs实现内部功能的功能。不是所有这些函数指针必须为给定类型定义。所需成员为nonzero,copyswap,copyswapn,setitem,getitem cast。这些假设为非NULL和NULL条目会导致程序崩溃。其他函数可以是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;
行为段的概念用于函数指针的描述。行为段是对齐的,并且以数据类型的本机机器字节顺序。nonzero,copyswap,copyswapn,getitem和setitem必须)处理误操作的数组。其他功能需要行为存储器段。
cast(void *from, void *to, npy_intp n, void *fromarr, void *toarr)一个数组的函数指针,从当前类型转换为所有其他内建类型。每个函数将指向的连续,对齐和未交换缓冲区从转换为指向的连续,对齐和未交换的缓冲区到给出的项目数量由n,参数fromarr和toarr被解释为PyArrayObjects,用于灵活数组获取itemsize信息。
getitem(void *data, void *arr)指向从数据指向的数组对象arr的单个元素返回标准Python对象的函数的指针。此功能必须能够正确处理“错误”(未对齐和/或交换)数组。
setitem(PyObject *item, void *data, void *arr)指向在数据指向的位置将Python对象项设置为数组arr的函数的指针。此函数处理“misbehaved”数组。如果成功,则返回零,否则返回负数(并设置Python错误)。
copyswapn(void *dest, npy_intp dstride, void *src, npy_intp sstride, npy_intp n, int swap, void *arr)copyswap(void *dest, void *src, int swap, void *arr)这些成员都是指向从src到dest和交换(如果指示)复制数据的函数的指针。arr的值仅用于灵活(NPY_STRING,NPY_UNICODE和NPY_VOID)数组(并且从arr->descr->elsize)。第二个函数复制单个值,而第一个函数使用提供的步长循环n个值。这些函数可以处理错误的src数据。如果src为NULL,则不执行复制。如果swap为0,则不会发生字节交换。假设dest和src不重叠。如果它们重叠,则首先使用memmove(...),然后使用NULL值src跟随copyswap(n)。
compare(const void* d1, const void* d2, void* arr)指向比较由d1和d2指向的数组的两个元素arr的函数的指针。此函数需要行为(对齐和不交换)数组。The return value is 1 if * d1 > * d2, 0 if * d1 == * d2, and -1 if * d1 < * d2. 数组对象arr用于检索灵活数组的项目大小和字段信息。
argmax(void* data, npy_intp n, npy_intp* max_ind, void* arr)指向arr中从data指向的元素开始检索n中最大元素的索引的函数的指针。这个函数要求内存段是连续的和行为的。返回值始终为0。最大元素的索引在max_ind中返回。
dotfunc(void* ip1, npy_intp is1, void* ip2, npy_intp is2, void* op, npy_intp n, void* arr)指向一个将两个n长序列相乘的函数的指针,将它们添加,并将结果放在arr的op 。两个序列的开始由ip1和ip2指向。要到达每个序列中的下一个元素,需要分别跳过is1和is2 字节。此函数需要行为(但不一定是连续的)内存。
scanfunc(FILE* fd, void* ip, void* sep, void* arr)指向一个函数的指针,该函数将相应类型的一个元素从文件描述符fd扫描(scanf style)到ip指向的数组内存。数组被假定为行为。如果sep不为NULL,则在返回之前还会从文件中扫描分隔符字符串。最后一个参数arr是要扫描的数组。如果扫描成功,返回0。负数表示发生错误:-1表示在扫描分隔符字符串之前到达文件结尾,-4表示在扫描元素之前到达文件结尾,-3表示该元素可以不能从格式字符串中解释。需要一个behaved数组。
fromstr(char* str, void* ip, char** endptr, void* arr)指向一个函数的指针,该函数将由str指向的字符串转换为相应类型的一个元素,并将它放在ip指向的内存位置。转换完成后,*endptr指向字符串的其余部分。最后一个参数arr是ip指向的数组(可变大小数据类型所需)。成功返回0或失败返回-1。需要一个behaved数组。
nonzero(void* data, void* arr)指向data指向的arr项目为非零的函数的指针。这个函数可以处理不正确的数组。
fill(void* data, npy_intp length, void* arr)指向一个函数的指针,该函数用数据填充给定长度的连续数组。数组的前两个元素必须已填充。从这两个值,将计算增量,并且将通过重复地添加该计算的增量来计算从项3到结束的值。数据缓冲器必须是良好的。
fillwithscalar(void* buffer, npy_intp length, void* value, void* arr)指向一个函数的指针,该函数使用给定地址的单个标量value填充给定length的连续buffer最后一个参数是获取可变长度数组的itemsize所需的数组。
sort(void* start, npy_intp length, void* arr)指向特定排序算法的函数指针的数组。使用键(到目前为止定义了NPY_QUICKSORT,NPY_HEAPSORT和NPY_MERGESORT)获得特定的排序算法。这些排序是在现场完成的,假设连续和对齐的数据。
argsort(void* start, npy_intp* result, npy_intp length, void *arr)用于此数据类型的排序算法的函数指针数组。可以使用与sort相同的排序算法。产生排序的索引在result(其必须用索引0到length-1)中返回。
castdictNULL或包含用户定义数据类型的低级别转换函数的字典。每个函数包裹在PyCObject *中,并由数据类型数字键入。
scalarkind(PyArrayObject* arr)用于确定如何解释此类型的标量的函数。参数是NULL或包含数据的0维数组(如果需要确定标量的种类)。返回值的类型必须为NPY_SCALARKIND。
cancastscalarkindtoNULL或数组NPY_NSCALARKINDS指针。这些指针应该是NULL或指向整数数组(由NPY_NOTYPE终止)的指针,指示指定类型的此数据类型的标量的数据类型可以安全地(这通常意味着不丧失精度)。
cancasttoNULL或整数数组(由NPY_NOTYPE终止)表示此数据类型可以安全转换的数据类型(这通常意味着不会丢失精度)。
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. 存储器段必须是连续的并且表现的,并且min或max可以是NULL,但不能两者。
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. 所有数组必须是连续的和行为的。
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_RAISE,NPY_WRAP或NPY_CLIP)决定索引小于0或大于nindarray将被处理。
argmin(void* data, npy_intp n, npy_intp* min_ind, void* arr)指向arr中data指向的元素开始检索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(...)来改变。
PyUFuncObjectufunc的核心是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;
PyUFuncObject.nin输入参数的数量。
PyUFuncObject.nout输出参数的数量。
PyUFuncObject.nargs参数的总数(nin + nout)。此值必须小于NPY_MAXARGS。
PyUFuncObject.identityPyUFunc_One,PyUFunc_Zero,PyUFunc_None或PyUFunc_AllOnes以指示此操作的身份。它只用于对空数组的reduce类调用。
void PyUFuncObject.functions(char ** args,npy_intp * dims,npy_intp * steps,void * extradata)函数指针的数组 - 一个用于ufunc支持的每个数据类型。这是被调用来实现底层函数dims [0]次的向量循环。第一个参数args是nargs指向行为内存的指针的数组。指向输入参数数据的指针是第一个,后跟指向输出参数数据的指针。必须跳过多少字节才能到达序列中的下一个元素,由步骤数组中的相应条目指定。最后一个参数允许循环接收额外的信息。这是通常使用的,使得单个通用向量循环可以用于多个函数。在这种情况下,要调用的实际标量函数以extradata形式传递。此函数指针数组的大小为ntypes。
PyUFuncObject.data如果不需要额外数据,则将额外数据传递到1-d向量循环或NULL。此C阵列必须与函数数组相同大小(,即 ntypes)。如果不需要extra_data,则使用NULL。对UFunc的几个C-API调用只是1-d向量循环,它使用这个额外的数据来接收指向实际调用的函数的指针。
PyUFuncObject.ntypesufunc支持的数据类型数。此数字指定(内置数据类型的)多少个不同的1-d循环可用。
PyUFuncObject.nameufunc的字符串名称。这被动态地用于构建ufuncs的__doc__属性。
PyUFuncObject.types
8位类型数的数组,其包含每种受支持(内置)数据类型的函数的类型签名。对于每个ntypes函数,此数组中相应的类型数集合显示如何在1-d向量循环中解释args参数。这些类型数字不必是相同的类型,并且支持混合型ufunc。
PyUFuncObject.docufunc的文档。不应该包含函数签名,因为这是在检索__doc__时动态生成的。
PyUFuncObject.ptr任何动态分配的内存。目前,这用于从一个python函数创建的动态ufuncs,为类型,数据和名称成员存储空间。
PyUFuncObject.obj对于从python函数动态创建的ufuncs,此成员持有对底层Python函数的引用。
PyUFuncObject.userloops用户定义的1-d向量循环(存储为CObject ptrs)的字典。用户可以为任何用户定义的类型注册循环。它按类型号检索。用户定义的类型数字始终大于NPY_USERDEF。
PyUFuncObject.op_flags覆盖每个ufunc操作数的默认操作数标志。
PyUFuncObject.iter_flags覆盖ufunc的默认nditer标志。
PyArrayIterObject对应于PyArrayIter_Type的对象的C结构是PyArrayIterObject。PyArrayIterObject用于跟踪指向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;
PyArrayIterObject.nd_m1
其中
是底层数组中的维数。
PyArrayIterObject.index到数组的当前1-d索引。
PyArrayIterObject.size底层数组的总大小。
PyArrayIterObject.coordinates到数组的
维索引。
PyArrayIterObject.dims_m1数组的大小在每个维度中减1。
PyArrayIterObject.strides数组的步幅。需要多少字节来跳转到每个维度中的下一个元素。
PyArrayIterObject.backstrides需要多少字节从维度的结尾跳回到它的开始。注意,背面[k] == strides [k] * dims_m1 [k ],但它在此处存储为优化。
PyArrayIterObject.factors该数组用于从1-d索引计算N-d索引。它包含所需的尺寸产品。
PyArrayIterObject.ao指向底层的ndarray的指针这个迭代器被创建来表示。
PyArrayIterObject.dataptr此成员指向由索引指示的ndarray中的元素。
PyArrayIterObject.contiguous如果基础数组为NPY_ARRAY_C_CONTIGUOUS,则此标志为真。如果可能,它用于简化计算。
如何在C级使用数组迭代器将在后面的章节中详细解释。通常,你不需要关心迭代器对象的内部结构,只需使用宏PyArray_ITER_NEXT(it),PyArray_ITER_GOTO it,dest)或PyArray_ITER_GOTO1D(it,index)。所有这些宏都需要参数it为PyArrayIterObject *。
PyArrayMultiIterObjecttypedef struct {
PyObject_HEAD
int numiter;
npy_intp size;
npy_intp index;
int nd;
npy_intp dimensions[NPY_MAXDIMS];
PyArrayIterObject *iters[NPY_MAXDIMS];
} PyArrayMultiIterObject;
PyArrayMultiIterObject.numiter需要广播到相同形状的数组的数量。
PyArrayMultiIterObject.size总广播尺寸。
PyArrayMultiIterObject.index当前(1-d)索引到广播结果中。
PyArrayMultiIterObject.nd广播结果中的维度数。
PyArrayMultiIterObject.dimensions广播结果的形状(仅使用nd个时隙)。
PyArrayMultiIterObject.iters一个迭代器对象的数组,它保存要一起广播的数组的迭代器。返回时,迭代器被调整用于广播。
PyArrayNeighborhoodIterObject对应于PyArrayNeighborhoodIter_Type的对象的C结构是PyArrayNeighborhoodIterObject。
对于可以出现在数组中的每个不同的内置数据类型,都有一个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_Type和PyUIntpArrType_Type,它们是可以在平台上保存指针的整数类型之一的简单替换。这些标量对象的结构不暴露给C代码。函数PyArray_ScalarAsCtype(..)可用于从数组标量提取C类型值,函数PyArray_Scalar(...)可用于构造数组标量从C值。
发现一些新的C结构在NumPy的开发中是有用的。这些C结构用在至少一个C-API调用中,因此在这里被记录。这些结构被定义的主要原因是使得使用Python ParseTuple C-API将Python对象转换为有用的C对象变得容易。
PyArray_Dims当想要解释形状和/或步幅信息时,这种结构是非常有用的。结构是:
typedef struct {
npy_intp *ptr;
int len;
} PyArray_Dims;
这个结构的成员是
PyArray_Dims.ptr指向通常表示数组形状或数组步长的(npy_intp)整数列表的指针。
PyArray_Dims.len整数列表的长度。假定安全地访问ptr [0]到ptr [len-1]。
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;
会员是
PyArray_Chunk.basePython对象这个内存块来自。需要,以便内存可以正确地解决。
PyArray_Chunk.ptr指向单段内存块的开始的指针。
PyArray_Chunk.len段的长度(以字节为单位)。
PyArray_Chunk.flags应用于解释内存的任何数据标志(例如 NPY_ARRAY_WRITEABLE)。
也可以看看
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;
PyArrayInterface.two整数2作为健全性检查。
PyArrayInterface.nd数组中的维数。
PyArrayInterface.typekind根据typestring约定用't' - >位字段,'b' - >布尔,'i' - >有符号整数,'u' - >无符号整数,'f' - >浮点,'c' - >复杂浮点,'O' - >对象,'S' - >(字节 - )字符串,'U' - > unicode,'V'
PyArrayInterface.itemsize数组中每个项目所需的字节数。
PyArrayInterface.flagsNPY_ARRAY_C_CONTIGUOUS(1),NPY_ARRAY_F_CONTIGUOUS(2),NPY_ARRAY_ALIGNED(0x100),NPY_ARRAY_NOTSWAPPED )或NPY_ARRAY_WRITEABLE(0x400)来表示数据。NPY_ARRAY_ALIGNED,NPY_ARRAY_C_CONTIGUOUS和NPY_ARRAY_F_CONTIGUOUS标志实际上可以从其他参数确定。还可以设置标志NPY_ARR_HAS_DESCR(0x800)以指示使用版本3数组接口的对象存在结构的descr成员(它将被消耗版本2的数组接口的对象忽略) )。
PyArrayInterface.shape包含每个维中数组大小的数组。
PyArrayInterface.strides包含要跳到每个维度中的下一个元素的字节数的数组。
PyArrayInterface.data指针到数组的第一个元素。
PyArrayInterface.descr更详细地描述数据类型的Python对象(与__array_interface__中的descr键相同)。如果typekind和itemize提供足够的信息,则可以NULL。除非标志中的ARR_HAS_DESCR标志为开,因此也会忽略此字段。
在内部,代码使用一些额外的Python对象主要用于内存管理。这些类型不能直接从Python访问,并且不暴露给C-API。它们在这里只是为了完整性和帮助理解代码。
PyUFuncLoopObject用于包含循环所需信息的C结构的松散包装器。如果你想了解ufunc循环代码,这是有用的。PyUFuncLoopObject是关联的C结构。它在ufuncobject.h头中定义。
PyUFuncReduceObjectC结构的松散包装,包含ufuncs的reduce类方法所需的信息。如果你想要理解reduce,accumulate和reduce-at代码,这很有用。PyUFuncReduceObject是关联的C结构。它在ufuncobject.h头中定义。
PyUFunc_Loop1d包含为用户定义的数据类型的每个定义的签名定义用于ufunc的1-d循环所需的信息的C结构的简单链接列表。