原文: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类型的层次结构。
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;
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.base
base-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
)中返回。
castdict
NULL
或包含用户定义数据类型的低级别转换函数的字典。每个函数包裹在PyCObject *
中,并由数据类型数字键入。
scalarkind
(PyArrayObject* arr)用于确定如何解释此类型的标量的函数。参数是NULL
或包含数据的0维数组(如果需要确定标量的种类)。返回值的类型必须为NPY_SCALARKIND
。
cancastscalarkindto
NULL
或数组NPY_NSCALARKINDS
指针。这些指针应该是NULL
或指向整数数组(由NPY_NOTYPE
终止)的指针,指示指定类型的此数据类型的标量的数据类型可以安全地(这通常意味着不丧失精度)。
cancastto
NULL
或整数数组(由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
项目的相应块拷贝到dest
clipmode
(可以取值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(...)来改变。
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;
PyUFuncObject.nin
输入参数的数量。
PyUFuncObject.nout
输出参数的数量。
PyUFuncObject.nargs
参数的总数(nin + nout)。此值必须小于NPY_MAXARGS
。
PyUFuncObject.identity
PyUFunc_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.ntypes
ufunc支持的数据类型数。此数字指定(内置数据类型的)多少个不同的1-d循环可用。
PyUFuncObject.name
ufunc的字符串名称。这被动态地用于构建ufuncs的__doc__属性。
PyUFuncObject.types
8位类型数的数组,其包含每种受支持(内置)数据类型的函数的类型签名。对于每个ntypes函数,此数组中相应的类型数集合显示如何在1-d向量循环中解释args参数。这些类型数字不必是相同的类型,并且支持混合型ufunc。
PyUFuncObject.doc
ufunc的文档。不应该包含函数签名,因为这是在检索__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 *
。
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;
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.base
Python对象这个内存块来自。需要,以便内存可以正确地解决。
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.flags
NPY_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
头中定义。
PyUFuncReduceObject
C结构的松散包装,包含ufuncs的reduce类方法所需的信息。如果你想要理解reduce,accumulate和reduce-at代码,这很有用。PyUFuncReduceObject
是关联的C结构。它在ufuncobject.h
头中定义。
PyUFunc_Loop1d
包含为用户定义的数据类型的每个定义的签名定义用于ufunc的1-d循环所需的信息的C结构的简单链接列表。