python类型和C结构¶
C代码中定义了几种新类型。其中大多数都可以从Python访问,但有一些由于使用有限而没有公开。每个新的python类型都有一个 PyObject *
内部结构包含指向“方法表”的指针,该“方法表”定义新对象在Python中的行为。当您在C代码中接收到一个python对象时,您总是得到一个指向 PyObject
结构。因为A PyObject
结构非常通用,只定义 PyObject_HEAD
它本身就不是很有趣。但是,不同的对象在 PyObject_HEAD
(但是您必须强制转换到正确的类型才能访问它们——或者使用访问函数或宏)。
定义了新的python类型¶
python类型在python类的C中是功能等价的。通过构造新的python类型,可以为python提供新的对象。ndarray对象是在C中定义的新类型的一个示例。新类型在C中通过两个基本步骤定义:
- 创建C结构(通常命名为
Py{{Name}}Object
)它是二进制的-与PyObject
结构本身,但保留该特定对象所需的附加信息; - 填充
PyTypeObject
表(由PyObject
结构)具有指向实现类型所需行为的函数的指针。
与定义Python类行为的特殊方法名不同,还有“函数表”指向实现所需结果的函数。自python 2.2以来,pytypeobject本身已经成为动态的,它允许C类型可以从C中的其他C类型“子类型化”,并在python中进行子类化。子类型从其父类型继承属性和方法。
有两种主要的新类型:ndarray( PyArray_Type
)和不明飞行物( PyUFunc_Type
)其他类型起到支持作用: PyArrayIter_Type
, the PyArrayMultiIter_Type
和 PyArrayDescr_Type
. 这个 PyArrayIter_Type
是ndarray的平面迭代器的类型(获取平面属性时返回的对象)。这个 PyArrayMultiIter_Type
调用时返回的对象类型 broadcast
()它处理嵌套序列集合上的迭代和广播。此外, PyArrayDescr_Type
是其实例描述数据的数据类型描述符类型。最后,有21个新的标量数组类型,它们是新的python scalar,对应于数组可用的每个基本数据类型。另外还有10种类型是占位符,它们允许数组标量适应实际的Python类型层次结构。
PyArray_Type¶
-
PyArray_Type
¶ ndarray的python类型是
PyArray_Type
. 在C语言中,每个ndarray都是指向PyArrayObject
结构。此结构的ob_类型成员包含指向PyArray_Type
Type对象。
-
PyArrayObject
¶ 这个
PyArrayObject
C-structure包含数组所需的所有信息。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
是任何数组的最大维度数。
-
PyObject *
PyArrayObject.base
¶ 此成员用于保存指向与此数组相关的另一个python对象的指针。有两个用例:1)如果此数组不拥有自己的内存,则指向拥有它的python对象(可能是另一个数组对象);2)如果此数组具有(已弃用)
NPY_ARRAY_UPDATEIFCOPY
或:c:data:npy_array_writebackifcopy`:标志集,则此数组是“行为不当”数组的工作副本。什么时候?PyArray_ResolveWritebackIfCopy
如果调用,则将使用此数组的内容更新基指向的数组。
-
PyArray_Descr *
PyArrayObject.descr
¶ 指向数据类型描述符对象的指针(见下文)。数据类型描述符对象是允许对内存进行一般描述的新内置类型的实例。每个支持的数据类型都有一个描述符结构。此描述符结构包含有关类型的有用信息以及指向函数指针表的指针,以实现特定功能。
-
int
PyArrayObject.flags
¶ 指示如何解释数据指向的内存的标志。可能的标志是
NPY_ARRAY_C_CONTIGUOUS
,NPY_ARRAY_F_CONTIGUOUS
,NPY_ARRAY_OWNDATA
,NPY_ARRAY_ALIGNED
,NPY_ARRAY_WRITEABLE
,NPY_ARRAY_WRITEBACKIFCOPY
和NPY_ARRAY_UPDATEIFCOPY
.
PyArrayDescr_Type¶
-
PyArrayDescr_Type
¶ 这个
PyArrayDescr_Type
是数据类型描述符对象的内置类型,用于描述如何解释组成数组的字节。静态定义21个PyArray_Descr
用于内置数据类型的对象。当它们参与引用计数时,它们的引用计数不应达到零。还有一个用户定义的动态表PyArray_Descr
也被维护的对象。一旦一个数据类型描述符对象被“注册”,它也不应该被释放。函数PyArray_DescrFromType
(…)可用于检索PyArray_Descr
来自枚举类型号(内置或用户定义)的对象。
-
PyArray_Descr
¶ 这个
PyArray_Descr
结构位于PyArrayDescr_Type
. 虽然这里描述它是为了完整性,但它应该被认为是内部的 NumPy 和操作通过PyArrayDescr_*
或PyDataType*
函数和宏。此结构的大小可能会随着numpy版本的不同而变化。为确保兼容性:- 从不声明结构的非指针实例
- 从不执行指针算术
- 从不使用
sizof(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类型。对于内置类型,这将指向相应的数组标量。对于用户定义的类型,这应该指向用户定义的类型对象。此typeobject可以从数组标量继承,也可以不从数组标量继承。如果它不是从数组标量继承的,那么
NPY_USE_GETITEM
和NPY_USE_SETITEM
标志应设置在flags
成员。
-
char
PyArray_Descr.kind
¶ 指示数组类型的字符代码(使用数组接口类型字符串表示法)。“b”表示布尔值,“i”表示有符号整数,“u”表示无符号整数,“f”表示浮点值,“c”表示复杂浮点值,“s”表示8位以零结尾的字节,“u”表示32位/字符的Unicode字符串,“v”表示任意值。
-
char
PyArray_Descr.type
¶ 指示数据类型的传统字符代码。
-
char
PyArray_Descr.byteorder
¶ 表示字节顺序的字符:“>”(big endian)、“<”(little-endian)、“=”(native)、“”(uncertible,ignore)。所有内置数据类型都具有byteorder“=”。
-
int
PyArray_Descr.flags
¶ 一个数据类型位标志,用于确定数据类型是否表现出类似于对象数组的行为。此成员中的每个位都是一个标志,其名称为:
-
NPY_ITEM_REFCOUNT
¶
-
NPY_LIST_PICKLE
¶ 指示此数据类型的数组必须在酸洗前转换为列表。
-
NPY_ITEM_IS_POINTER
¶ 指示该项是指向其他数据类型的指针
-
NPY_NEEDS_INIT
¶ 指示创建时必须初始化此数据类型的内存(设置为0)。
-
NPY_NEEDS_PYAPI
¶ 指示此数据类型在访问期间需要python c-api(因此,如果需要数组访问,不要放弃gil)。
-
NPY_USE_GETITEM
¶ 在阵列访问时使用
f->getitem
函数指针,而不是数组标量的标准转换。如果不定义数组标量与数据类型一起使用,则必须使用。
-
NPY_USE_SETITEM
¶ 从数组标量创建0-D数组时,请使用
f->setitem
而不是数组标量的标准副本。如果不定义数组标量与数据类型一起使用,则必须使用。
-
NPY_FROM_FIELDS
¶ 如果在数据类型的任何字段中设置了这些位,则为父数据类型继承的位。目前(
NPY_NEEDS_INIT
NPY_LIST_PICKLE
NPY_ITEM_REFCOUNT
NPY_NEEDS_PYAPI
)
-
NPY_OBJECT_DTYPE_FLAGS
¶ 为对象数据类型设置的位:(
NPY_LIST_PICKLE
NPY_USE_GETITEM
NPY_ITEM_IS_POINTER
NPY_REFCOUNT
NPY_NEEDS_INIT
NPY_NEEDS_PYAPI
)
-
PyDataType_FLAGCHK
(PyArray_Descr *dtype, int flags)¶ 如果为数据类型对象设置了所有给定标志,则返回true。
-
PyDataType_REFCHK
(PyArray_Descr *dtype)¶ 相当于
PyDataType_FLAGCHK
( D型 ,NPY_ITEM_REFCOUNT
)
-
-
int
PyArray_Descr.type_num
¶ 唯一标识数据类型的数字。对于新数据类型,此编号在注册数据类型时分配。
-
int
PyArray_Descr.elsize
¶ 对于总是大小相同(如long)的数据类型,这将保留数据类型的大小。对于不同数组可以具有不同元素大小的灵活数据类型,此值应为0。
-
int
PyArray_Descr.alignment
¶ 提供此数据类型的对齐信息的数字。具体来说,它显示了2元素结构(其第一个元素是
char
)编译器放置此类型的项:offsetof(struct {{char c; type v;}}, v)
-
PyArray_ArrayDescr *
PyArray_Descr.subarray
¶ 如果这不是
NULL
,则此数据类型描述符是另一个数据类型描述符的C样式连续数组。换句话说,这个描述符描述的每个元素实际上是一些其他基本描述符的数组。对于另一个数据类型描述符中的字段,这是最有用的数据类型描述符。字段成员应为NULL
如果这不是NULL
(基本描述符的字段成员可以是非-NULL
然而)。这个PyArray_ArrayDescr
结构定义使用typedef struct { PyArray_Descr *base; PyObject *shape; } PyArray_ArrayDescr;
这种结构的要素是:
-
PyArray_Descr *
PyArray_ArrayDescr.base
¶ 基类型的数据类型描述符对象。
-
PyArray_Descr *
-
PyObject *
PyArray_Descr.fields
¶ 如果这不是空值,那么这个数据类型描述符具有由Python字典描述的字段,这些字段的键是名称(如果给定,还包括标题),其值是描述这些字段的元组。回想一下,数据类型描述符总是描述一组固定长度的字节。字段是该固定长度集合的命名子区域。字段由另一个数据类型描述符和字节偏移量组成的元组来描述。或者,元组可以包含通常是Python字符串的标题。这些元组放在这个字典中,按名称键控(如果给定的话还有标题)。
-
PyArray_ArrFuncs *
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
函数可以(并且必须)处理行为不正确的数组。其他函数需要行为内存段。-
void
cast
(void *from, void *to, npy_intp n, void *fromarr, void *toarr)¶ 要从当前类型转换为所有其他内置类型的函数指针数组。每个函数都强制转换一个连续的、对齐的和不交换的缓冲区 from 指向一个连续的、对齐的、没有交换的缓冲区 to 要强制转换的项目数由 n 和参数 弗罗马尔 和 托尔 被解释为灵活数组的pyarrayobjects以获取项大小信息。
-
PyObject *
getitem
(void *data, void *arr)¶ 指向从数组对象的单个元素返回标准python对象的函数的指针。 arr 指向 data . 此函数必须能够正确处理“行为不当”(未对齐和/或交换)数组。
-
int
setitem
(PyObject *item, void *data, void *arr)¶ 指向设置python对象的函数的指针 item 进入数组, arr ,在指向的位置 data . 此函数用于处理“行为不正常”的数组。如果成功,则返回零,否则返回负的零(以及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)¶ 这些成员都是指向要从中复制数据的函数的指针 src 到 dest 和 swap 如有指示。arr值仅用于灵活(
NPY_STRING
,NPY_UNICODE
和NPY_VOID
)数组(从arr->descr->elsize
)第二个函数复制一个值,而第一个函数用提供的步幅循环n个值。这些函数可以处理不当行为 src 数据。如果 src 为空,则不执行任何复制。如果 swap 为0,则不发生字节交换。假设 dest 和 src 不要重叠。如果它们重叠,则使用memmove
(…)先是后是copyswap(n)
值为空的src
.
-
int
compare
(const void* d1, const void* d2, void* arr)¶ 指向比较数组两个元素的函数的指针,
arr
指向d1
和d2
. 此函数需要行为(对齐和不交换)的数组。如果 *d1
> *d2
0,如果 *d1
== *d2
和-1如果 *d1
< *d2
. 数组对象arr
用于检索灵活数组的项大小和字段信息。
-
int
argmax
(void* data, npy_intp n, npy_intp* max_ind, void* arr)¶ 指向函数的指针,该函数检索
n
元素在arr
从指向的元素开始data
. 此函数要求内存段是连续的并具有行为。返回值始终为0。返回最大元素的索引max_ind
.
-
void
dotfunc
(void* ip1, npy_intp is1, void* ip2, npy_intp is2, void* op, npy_intp n, void* arr)¶ 指向将两个数相乘的函数的指针
n
-将长度序列加在一起,并将结果放入指向的元素中op
属于arr
. 两个序列的开头由ip1
和ip2
. 要到达每个序列中的下一个元素,需要跳到is1
和is2
字节 ,分别。此函数需要行为(尽管不一定是连续的)内存。
-
int
scanfunc
(FILE* fd, void* ip, void* sep, void* arr)¶ 指向函数的指针,该函数从文件描述符扫描(scanf样式)相应类型的一个元素。
fd
指向的数组内存ip
. 假定数组的行为。如果sep
不为空,则在返回之前还将从文件扫描分隔符字符串。最后一个论点arr
是要扫描到的数组。如果扫描成功,则返回0。负数表示出现错误:1表示在扫描分隔符字符串之前已到达文件结尾,-4表示在扫描元素之前已到达文件结尾,-3表示无法从格式字符串解释元素。需要行为数组。
-
int
fromstr
(char* str, void* ip, char** endptr, void* arr)¶ 指向函数的指针,该函数将指向的字符串转换为
str
对应类型的一个元素,并将其放置在指向的内存位置ip
. 转换完成后,*endptr
指向字符串的其余部分。最后一个论点arr
是IP点所在的数组(对于可变大小的数据类型是必需的)。成功时返回0,失败时返回-1。需要行为数组。
-
Bool
nonzero
(void* data, void* arr)¶ 指向函数的指针,如果
arr
指向data
是非零。此函数可以处理行为错误的数组。
-
void
fill
(void* data, npy_intp length, void* arr)¶ 指向函数的指针,该函数用数据填充给定长度的连续数组。数组的前两个元素必须已填充。从这两个值中,将计算一个增量,并通过重复添加此计算的增量来计算从项目3到末尾的值。数据缓冲区必须运行良好。
-
void
fillwithscalar
(void* buffer, npy_intp length, void* value, void* arr)¶ 指向函数的指针,该函数填充一个连续的
buffer
给定的length
使用单个标量value
地址是谁的。最后一个参数是获取可变长度数组的itemsize所需的数组。
-
int
sort
(void* start, npy_intp length, void* arr)¶ 指向特定排序算法的函数指针数组。一个特殊的排序算法是用一个键(到目前为止
NPY_QUICKSORT
,NPY_HEAPSORT
和NPY_MERGESORT
定义。这些排序是在假定连续和对齐数据的情况下进行的。
-
int
argsort
(void* start, npy_intp* result, npy_intp length, void *arr)¶ 指向此数据类型排序算法的函数指针数组。可使用与排序相同的排序算法。产生排序的索引返回到
result
(必须用索引0初始化到length-1
包括在内)。
-
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)¶ 一个读取
n_in
项目来自in
并写入out
读取值,如果它在min
和max
或相应的限制(如果在外部)。内存段必须是连续的且行为良好,并且min
或max
可能是NULL
,但不是两者兼而有之。
-
void
fastputmask
(void *in, void *mask, npy_intp n_in, void *values, npy_intp nv)¶ 接受指针的函数
in
一组数组n_in
项目,指针mask
一组数组n_in
布尔值和指针vals
一组数组nv
项目。项目来自vals
被复制到in
无论价值在哪里mask
为非零,平铺vals
如果需要,如果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)¶ 接受指针的函数
src
C连续的行为段,解释为三维形状数组(n_outer, nindarray, nelem)
一个指针indarray
到m_middle
整数索引和指针dest
C连续的行为段,解释为三维形状数组(n_outer, m_middle, nelem)
. 指数indarray
用于索引src
沿着第二维度,复制nelem
项目纳入dest
.clipmode
(可以接受值NPY_RAISE
,NPY_WRAP
或NPY_CLIP
)确定小于0或大于0的索引nindarray
将被处理。
-
void
这个 PyArray_Type
typeobject实现了python对象的许多特性,包括tp_as_number、tp_as_sequence、tp_as_mapping和tp_as_buffer接口。富比较(tp_richcare)还与方法(tp_methods)和属性(tp_getset)的新型属性查找一起使用。这个 PyArray_Type
也可以是子类型。
小技巧
tp_as_number方法使用通用方法调用已注册用于处理操作的任何函数。函数pynumeric_setops(..)可用于注册函数以处理特定的数学运算(对于所有数组)。当导入umath模块时,它将所有数组的数值操作设置为相应的ufunc。tp-str和tp-repr方法也可以使用pystring-setStringFunction(…)进行更改。
PyUFunc_Type¶
-
PyUFunc_Type
¶ 通过创建
PyUFunc_Type
. 它是一个非常简单的类型,只实现基本的getattribute行为、打印行为,并且具有允许这些对象像函数一样工作的调用行为。UFUNC背后的基本思想是为支持该操作的每个数据类型保存对快速一维(矢量)循环的引用。这些一维循环都具有相同的签名,并且是创建新UFUNC的关键。它们由通用循环代码调用,以实现N维函数。还有一些为浮动和复杂浮动数组定义的通用一维循环,允许您使用单个标量函数定义UFUNC。( e.g. 阿坦纳)
-
PyUFuncObject
¶ UFunc的核心是
PyUFuncObject
它包含调用执行实际工作的底层C代码循环所需的所有信息。虽然这里描述它是为了完整性,但它应该被认为是内部的 NumPy 和操作通过PyUFunc_*
功能。此结构的大小可能会随着numpy版本的不同而变化。为确保兼容性:- 从不声明结构的非指针实例
- 从不执行指针运算
- 从不使用
sizeof(PyUFuncObject)
其结构如下:
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; int core_enabled; int core_num_dim_ix; int *core_num_dims; int *core_dim_ixs; int *core_offsets; char *core_signature; PyUFunc_TypeResolutionFunc *type_resolver; PyUFunc_LegacyInnerLoopSelectionFunc *legacy_inner_loop_selector; PyUFunc_MaskedInnerLoopSelectionFunc *masked_inner_loop_selector; npy_uint32 *op_flags; npy_uint32 *iter_flags; /* new in API version 0x0000000D */ npy_intp *core_dim_sizes; npy_intp *core_dim_flags; } PyUFuncObject;
-
int
PyUFuncObject.nin
¶ 输入参数的数目。
-
int
PyUFuncObject.nout
¶ 输出参数的数目。
-
int
PyUFuncObject.nargs
¶ 参数总数( nin + nout )这个必须小于
NPY_MAXARGS
.
-
int
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 ,是一个数组 纳尔格斯 指向行为内存的指针。输入参数的数据指针是第一个,后面是输出参数的数据指针。必须跳过多少字节才能到达序列中的下一个元素由中的相应条目指定 步骤 数组。最后一个参数允许循环接收额外的信息。这是常用的,因此一个通用的向量循环可以用于多个函数。在这种情况下,要调用的实际标量函数作为 超文本 . 此函数指针数组的大小为类型。
-
void **
PyUFuncObject.data
¶ 要传递给一维向量循环的额外数据,或
NULL
如果不需要额外的数据。此C数组的大小必须相同( i.e. 键入)作为函数数组。NULL
如果不需要额外的数据,则使用。几个对ufunc的C-API调用只是使用这些额外数据来接收指向要调用的实际函数的指针的一维向量循环。
-
int
PyUFuncObject.ntypes
¶ UFUNC支持的数据类型数。这个数字指定有多少不同的一维循环(内置数据类型)可用。
-
int
PyUFuncObject.reserved1
¶ 未使用的
-
char *
PyUFuncObject.name
¶ ufunc的字符串名称。它动态地用于构建 __doc__ UFUNC的属性。
-
char *
PyUFuncObject.types
¶ 一个数组 nargs \times ntypes 8位类型_号,包含每个受支持(内置)数据类型的函数的类型签名。对于每一个 n型 函数,该数组中相应的一组类型号显示 args 参数应该在一维向量循环中解释。这些类型号不必是同一类型,并且支持混合类型UFunc。
-
char *
PyUFuncObject.doc
¶ UFUNC文件。不应包含函数签名,因为当 __doc__ 检索。
-
void *
PyUFuncObject.ptr
¶ 任何动态分配的内存。目前,它用于从python函数创建的动态ufunc,以存储类型、数据和名称成员的空间。
-
PyObject *
PyUFuncObject.userloops
¶ 用户定义类型的用户定义的一维向量循环(存储为cobject ptrs)的字典。用户可以为任何用户定义的类型注册循环。它是按类型编号检索的。用户定义的类型号始终大于
NPY_USERDEF
.
-
int
PyUFuncObject.core_enabled
¶ 标量UFunc为0;广义UFunc为1
-
int
PyUFuncObject.core_num_dim_ix
¶ 签名中不同的核心维度名称数
-
int *
PyUFuncObject.core_num_dims
¶ 每个参数的核心维数
-
int *
PyUFuncObject.core_dim_ixs
¶ 扁平形式的维数索引;参数索引
k
存储在core_dim_ixs[core_offsets[k] : core_offsets[k] + core_numdims[k]]
-
int *
PyUFuncObject.core_offsets
¶ 每个参数的第一个核心维度的位置
core_dim_ixs
,相当于cumsum (core_num_dims
)
-
char *
PyUFuncObject.core_signature
¶ 核心签名字符串
-
PyUFunc_TypeResolutionFunc *
PyUFuncObject.type_resolver
¶ 一种函数,它解析类型并用输入和输出的数据类型填充数组。
-
PyUFunc_LegacyInnerLoopSelectionFunc *
PyUFuncObject.legacy_inner_loop_selector
¶ 返回内部循环的函数。这个
legacy
因为numpy 1.6已经计划了一个更好的变种。这个变种还没有出现。
-
void *
PyUFuncObject.reserved2
¶ 对于将来可能具有不同签名的循环选择器。
-
PyUFunc_MaskedInnerLoopSelectionFunc *
PyUFuncObject.masked_inner_loop_selector
¶ 函数,返回ufunc的屏蔽内部循环
-
npy_uint32
PyUFuncObject.op_flags
¶ 覆盖每个ufunc操作数的默认操作数标志。
-
npy_uint32
PyUFuncObject.iter_flags
¶ 覆盖ufunc的默认nditer标志。
在API版本0x000000D中添加
-
npy_uint32 *
PyUFuncObject.core_dim_flags
¶ 对于每个不同的核心维度,一组
UFUNC_CORE_DIM*
旗帜UFUNC_CORE_DIM_CAN_IGNORE
if the dim name ends in?
UFUNC_CORE_DIM_SIZE_INFERRED
如果将从操作数而不是从 frozen 签名
PyArrayIter_Type¶
-
PyArrayIter_Type
¶ 这是一个迭代器对象,它使遍历N维数组变得容易。它是从ndarray的flat属性返回的对象。在整个实现内部,它也被广泛地用于在N维数组上循环。实现了tp_as_映射接口,这样迭代器对象就可以被索引(使用一维索引),并且通过tp_方法表实现了一些方法。这个对象实现了下一个方法,并且可以在迭代程序可以在Python中使用的任何地方使用。
-
PyArrayIterObject
¶ 对应于对象的C结构
PyArrayIter_Type
是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;
-
int
PyArrayIterObject.nd_m1
¶ N-1 在哪里? N 是基础数组中的维度数。
-
npy_intp *
PyArrayIterObject.backstrides
¶ 需要多少字节才能从维度的结尾跳回到它的开头。注意
backstrides[k] == strides[k] * dims_m1[k]
,但它存储在这里作为优化。
-
PyArrayObject *
PyArrayIterObject.ao
¶ 指向此迭代器创建用于表示的基础ndarray的指针。
-
char *
PyArrayIterObject.dataptr
¶ 此成员指向由索引指示的ndarray中的元素。
-
Bool
PyArrayIterObject.contiguous
¶ 如果基础数组是
NPY_ARRAY_C_CONTIGUOUS
. 它用于尽可能简化计算。
-
int
如何在C级上使用数组迭代器将在后面的章节中更详细地解释。通常,您不需要关心迭代器对象的内部结构,只需要通过使用宏与它进行交互。 PyArray_ITER_NEXT
(它) PyArray_ITER_GOTO
(IT,DEST),或 PyArray_ITER_GOTO1D
(IT,索引)。所有这些宏都需要参数 it 成为一个 PyArrayIterObject *
.
PyArrayMultiIter_Type¶
-
PyArrayMultiIter_Type
¶ 这种类型提供了一个迭代器,它封装了广播的概念。它允许 N 要一起广播的数组,以便循环在广播的数组上以C样式的连续方式进行。相应的C结构是
PyArrayMultiIterObject
其内存布局必须以任何对象开头, obj ,传递给PyArray_Broadcast
(obj)功能。通过调整数组迭代器来执行广播,以便每个迭代器表示广播的形状和大小,但调整其步幅,以便在每次迭代中使用数组中的正确元素。
-
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
¶ 需要广播到同一形状的数组数。
-
int
PyArrayMultiIterObject.nd
¶ 广播结果中的维度数。
-
PyArrayIterObject **
PyArrayMultiIterObject.iters
¶ 一个迭代器对象数组,用于保存迭代器以便将数组一起广播。返回时,迭代器被调整为广播。
-
int
PyArrayNeighborhoodIter_Type¶
-
PyArrayNeighborhoodIter_Type
¶ 这是一个迭代器对象,它使得在n维邻域上循环变得容易。
-
PyArrayNeighborhoodIterObject
¶ 对应于对象的C结构
PyArrayNeighborhoodIter_Type
是PyArrayNeighborhoodIterObject
.
PyArrayFlags_Type¶
-
PyArrayFlags_Type
¶ 从python中检索flags属性时,将构造此类型的特殊内置对象。这种特殊的类型通过将不同的标志作为属性访问,或者像对象是一个字典一样将标志名作为条目访问,使得使用不同的标志更加容易。
ScalarArrayTypes¶
对于数组中可能存在的每种不同的内置数据类型,都有一个python类型,其中大多数都是简单的包装器,围绕C中相应的数据类型。这些类型的C名称是 Py{{TYPE}}ArrType_Type
在哪里? {{TYPE}}
可以是
Bool , Byte , 短 , Int , Long , LongLong , UByte , UShort , UInt , ULong , ULongLong , Half , 浮标 , 双重的 , LongDouble , CFloat , CDouble , CLongDouble , 弦 , 统一码 , Void 和 对象 .
这些类型名是C-API的一部分,因此可以在扩展C代码中创建。还有一个 PyIntpArrType_Type
和A PyUIntpArrType_Type
这是可以在平台上保存指针的整数类型之一的简单替换。这些标量对象的结构不向C代码公开。函数 PyArray_ScalarAsCtype
(..)可用于从数组标量和函数中提取C类型值 PyArray_Scalar
(…)可用于从C值构造数组标量。
其他C结构¶
一些新的C结构被发现在numpy的开发中是有用的。这些C结构至少在一个C-API调用中使用,因此在这里进行了记录。定义这些结构的主要原因是为了便于使用python parsetuple C-api将python对象转换为有用的C对象。
PyArray_Dims¶
PyArray_Chunk¶
-
PyArray_Chunk
¶ 这相当于python中的缓冲区对象结构,直到ptr成员为止。在32位平台上( i.e. 如果
NPY_SIZEOF_INT
=NPY_SIZEOF_INTP
,len成员还与缓冲区对象的等效成员匹配。表示通用的单段内存块很有用。typedef struct { PyObject_HEAD PyObject *base; void *ptr; npy_intp len; int flags; } PyArray_Chunk;
成员是
-
void *
PyArray_Chunk.ptr
¶ 指向单段内存块开头的指针。
-
int
PyArray_Chunk.flags
¶ 任何数据标志( e.g.
NPY_ARRAY_WRITEABLE
)这应该用来解释记忆。
-
void *
PyArrayInterface¶
参见
-
PyArrayInterface
¶ 这个
PyArrayInterface
结构的定义使得numpy和其他扩展模块可以使用快速阵列接口协议。这个__array_struct__
支持快速数组接口协议的对象的方法应返回PyCObject
包含指向PyArrayInterface
具有数组的相关详细信息的结构。创建新数组后,属性应为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”->(byte)字符串、“u”->unicode、“v”->void指示存在哪种类型的数组。
-
int
PyArrayInterface.itemsize
¶ 数组中每个项所需的字节数。
-
int
PyArrayInterface.flags
¶ 任何比特
NPY_ARRAY_C_CONTIGUOUS
(1)NPY_ARRAY_F_CONTIGUOUS
(2)NPY_ARRAY_ALIGNED
(0x100)NPY_ARRAY_NOTSWAPPED
(0x200),或NPY_ARRAY_WRITEABLE
(0x400)指示有关数据的内容。这个NPY_ARRAY_ALIGNED
,NPY_ARRAY_C_CONTIGUOUS
和NPY_ARRAY_F_CONTIGUOUS
标志实际上可以从其他参数中确定。旗NPY_ARR_HAS_DESCR
(0x800)也可以设置为指示使用版本3数组接口的对象存在结构的DESCR成员(使用版本2数组接口的对象将忽略该成员)。
-
void *
PyArrayInterface.data
¶ 指针 to 数组的第一个元素。
-
PyObject *
PyArrayInterface.descr
¶ 更详细地描述数据类型的python对象(与 德克思 键入
__array_interface__
)这可以NULL
如果 类型 和 项目尺寸 提供足够的信息。此字段也将被忽略,除非ARR_HAS_DESCR
标志在 旗帜 .
-
int
内部使用的结构¶
在内部,代码主要使用一些额外的python对象进行内存管理。这些类型不能直接从Python访问,也不能公开给C-API。这里包含它们只是为了完整性和帮助理解代码。
-
PyUFuncLoopObject
¶ 包含循环所需信息的C结构的松散包装。如果您试图理解ufunc循环代码,这很有用。这个
PyUFuncLoopObject
是相关的C结构。它在ufuncobject.h
标题。
-
PyUFuncReduceObject
¶ 一种C结构的松散包装物,其中包含了UFUNC的类还原方法所需的信息。如果您试图理解代码的reduce、accumulate和reduce,这是很有用的。这个
PyUFuncReduceObject
是相关的C结构。它在ufuncobject.h
标题。
-
PyUFunc_Loop1d
¶ 一个简单的C结构链接列表,其中包含为用户定义数据类型的每个已定义签名为UFUNC定义一维循环所需的信息。
-
PyArrayMapIter_Type
¶ 高级索引是用这种python类型处理的。它只是一个围绕C结构的松散包装,其中包含高级数组索引所需的变量。相关的C-结构,
PyArrayMapIterObject
,对于试图理解高级索引映射代码很有用。它在arrayobject.h
标题。此类型不向Python公开,可以用C结构替换。作为一种python类型,它利用了引用计数内存管理。