NumPy参考 >NumPy C-API > Python Types and C-Structures
C代码中定义了几种新类型。这些中的大多数都可以从Python访问,但由于使用受限,因此其中一些不公开。每个新的Python类型都有一个与内部结构相关联的内部结构,该内部结构包含指向“方法表”的指针,该方法定义了新对象在Python中的行为。当您将Python对象接收到C代码中时,总会得到一个指向结构的指针
。因为结构非常通用并且仅定义,所以它不是很有趣。但是,不同的对象在之后包含更多详细信息(但必须强制转换为正确的类型才能访问它们-或使用访问器函数或宏)。PyObject *
PyObject
PyObject
PyObject_HEAD
PyObject_HEAD
Python类型与Python中类的C函数等效。通过构造新的Python类型,可以为Python提供一个新对象。ndarray对象是用C定义的新类型的示例。新的类型在C中通过两个基本步骤定义:
创建一个C结构(通常称为Py{Name}Object
),该PyObject
结构与该结构本身具有二进制兼容性,但保留该特定对象所需的其他信息;
使用指向实现该类型所需行为的函数的指针填充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类型的层次结构。
PyArray_Type
¶ndarray的Python类型是PyArray_Type
。在C语言中,每个ndarray都是指向PyArrayObject
结构的指针。此结构的ob_type成员包含一个指向PyArray_Type
typeobject 的指针。
PyArrayObject
¶的PyArrayObject
C-结构包含所有用于阵列所需的信息。ndarray(及其子类)的所有实例都将具有此结构。为了将来的兼容性,通常应使用提供的宏来访问这些结构成员。如果您需要一个较短的名称,则可以使用NPY_AO
(已弃用),该名称定义为等效
PyArrayObject
。不建议直接访问struct字段。请改用PyArray _ *(arr)形式。
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.PyObject_HEAD
¶所有Python对象都需要这样做。它至少由一个引用计数成员(ob_refcnt
)和一个指向类型对象(ob_type
)的指针组成。(如果使用特殊选项编译Python,则其他元素也可能存在,有关更多信息,请参见Python源代码树中的Include / object.h)。ob_type成员指向Python类型对象。
PyArrayObject.data
¶可通过访问PyArray_DATA
该数据成员,它是指向数组第一个元素的指针。可以(通常应该)将此指针重铸为数组的数据类型。
PyArrayObject.nd
¶一个整数,提供此数组的维数。当nd为0时,该数组有时称为Rank-0数组。这样的数组具有未定义的尺寸和跨度,无法访问。中PyArray_NDIM
定义的
宏ndarraytypes.h
指向此数据成员。NPY_MAXDIMS
是任何数组的最大维度数。
PyArrayObject.dimensions
¶整数数组,每个维度的形状最长为nd1 。该整数始终足够大以将指针保持在平台上,因此维度大小仅受内存限制。
PyArray_DIMS
是与此数据成员关联的宏。
PyArrayObject.strides
¶整数数组,为每个维提供到达该维的下一个元素必须跳过的字节数。与宏关联PyArray_STRIDES
。
PyArrayObject.base
¶由指向PyArray_BASE
,该成员用于保存指向与此数组相关的另一个Python对象的指针。有两种用例:
如果此数组不拥有自己的内存,则基点指向拥有该内存的Python对象(也许是另一个数组对象)
如果此数组设置了(不赞成使用的)NPY_ARRAY_UPDATEIFCOPY
或
NPY_ARRAY_WRITEBACKIFCOPY
标志,则此数组是“行为不当”数组的工作副本。
当PyArray_ResolveWritebackIfCopy
被调用时,该阵列所指向的基将与此数组的内容进行更新。
PyArrayObject.descr
¶指向数据类型描述符对象的指针(请参见下文)。数据类型描述符对象是新的内置类型的实例,该实例允许对内存进行通用描述。每个支持的数据类型都有一个描述符结构。该描述符结构包含有关类型的有用信息,以及指向用于实现特定功能的函数指针表的指针。顾名思义,它与宏关联PyArray_DESCR
。
PyArrayObject.flags
¶由宏指向PyArray_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
是内置型的数据类型描述符的对象用于描述包含在阵列中的字节是如何被解释。PyArray_Descr
内置数据类型有21个静态定义的
对象。尽管这些都参与了参考计数,但它们的参考计数绝不能达到零。还有一个用户定义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 flags;
int type_num;
int elsize;
int alignment;
PyArray_ArrayDescr *subarray;
PyObject *fields;
PyObject *names;
PyArray_ArrFuncs *f;
PyObject *metadata;
NpyAuxData *c_metadata;
npy_hash_t hash;
} PyArray_Descr;
PyArray_Descr.typeobj
¶指向一个类型对象的指针,该对象是此数组元素的相应Python类型。对于内置类型,这指向相应的数组标量。对于用户定义的类型,这应指向用户定义的类型对象。此类型对象可以继承自数组标量,也可以不继承。如果它不继承自数组标量,则应在成员中设置NPY_USE_GETITEM
和
NPY_USE_SETITEM
标志flags
。
PyArray_Descr.kind
¶指示数组类型的字符代码(使用数组接口的类型字符串表示法)。“ b”代表布尔值,“ i”代表有符号整数,“ u”代表无符号整数,“ f”代表浮点数,“ c”代表复数浮点,“ S”代表8位零终止字节, “ U”代表32位/字符Unicode字符串,“ V”代表任意字符串。
PyArray_Descr.type
¶指示数据类型的传统字符代码。
PyArray_Descr.byteorder
¶指示字节顺序的字符:“>”(大端),“ <”(小端),“ =”(本机),“ |” (无关紧要,忽略)。所有内置数据类型的字节序均为“ =”。
PyArray_Descr.flags
¶数据类型位标志,用于确定该数据类型是否表现出类似对象数组的行为。该成员中的每个位都是一个标志,命名为:
NPY_ITEM_HASOBJECT
¶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维数组时,请使用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 标志)¶如果为数据类型对象设置了所有给定标志,则返回true。
PyDataType_REFCHK
(PyArray_Descr * dtype )¶等效于PyDataType_FLAGCHK
(dtype,
NPY_ITEM_REFCOUNT
)。
PyArray_Descr.type_num
¶一个唯一标识数据类型的数字。对于新的数据类型,该编号在注册数据类型时分配。
PyArray_Descr.elsize
¶对于始终具有相同大小(例如长)的数据类型,这将保留数据类型的大小。对于不同数组可以具有不同元素大小的灵活数据类型,应为0。
PyArray_Descr.alignment
¶提供此数据类型的对齐信息的数字。具体来说,它显示了从2元素结构(其第一个元素是a char
)的起点开始,编译器放置了以下类型的项目:offsetof(struct {char c; type v;},
v)
PyArray_Descr.subarray
¶如果不是NULL
,则此数据类型描述符是另一个数据类型描述符的C样式连续数组。换句话说,此描述符描述的每个元素实际上是一些其他基本描述符的数组。这是另一个数据类型描述符中字段的数据类型描述符时最有用的。NULL
如果不是,则fields成员应该为NULL
(但基本描述符的fields成员可以为non- NULL
)。该PyArray_ArrayDescr
结构使用
typedef struct {
PyArray_Descr *base;
PyObject *shape;
} PyArray_ArrayDescr;
该结构的元素是:
PyArray_ArrayDescr.base
¶基本类型的数据类型描述符对象。
PyArray_Descr.fields
¶如果这是非NULL,则此数据类型描述符具有由Python字典描述的字段,该字典的键为名称(如果有给定,则为标题),其值是描述这些字段的元组。回想一下,数据类型描述符总是描述一组固定长度的字节。字段是整个固定长度集合的命名子区域。通过由另一个数据类型描述符和字节偏移量组成的元组来描述字段。(可选)元组可以包含标题,该标题通常是Python字符串。这些元组放置在该词典中,并以名称(以及标题(如果提供))为关键字。
PyArray_Descr.f
¶指向结构的指针,该结构包含该类型需要实现内部功能的功能。这些功能与后面描述的通用功能(ufuncs)不同。他们的签名可以任意变化。
PyArray_Descr.c_metadata
¶特定dtype的C实现特定的元数据。为NumPy 1.7.0添加。
PyArray_Descr.hash
¶目前未使用。保留以供将来在缓存哈希值时使用。
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 )[ 源代码)¶从当前类型转换为所有其他内置类型的函数指针数组。每个功能蒙上了连续的,对齐,和notswapped在由缓冲尖 从一个连续的,对齐,和notswapped缓冲区指向由到项铸造的数量由下式给出Ñ,和参数fromarr和toarr被解释为PyArrayObjects为灵活的数组以获取项目大小信息。
getitem
( void * data,void * arr )[源代码)¶指向一个函数的指针,该函数从data指向 的数组对象arr的单个元素中返回标准Python对象。此函数必须能够正确处理“行为异常”(未对齐和/或交换)的数组。
setitem
(PyObject * item,void * data,void * arr )¶指向将Python对象项设置为data 所指位置 的数组arr的函数的指针 。此函数处理“行为异常”的数组。如果成功,则返回零,否则,返回负1(并设置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
(...),然后使用copyswap(n)
NULL值
src
。
compare
( const void * d1,const void * d2,void * arr )¶指向比较数组两个元素的函数的指针arr
,由d1
和指向d2
。此函数需要行为(对齐且未交换)的数组。如果* d1
> * d2
,则返回值为1 ;如果* d1
== *
d2
,则返回值为0;如果* d1
<* ,则返回-1 d2
。数组对象arr
用于检索灵活数组的项目大小和字段信息。
argmax
( void * data,npy_intp n,npy_intp * max_ind,void * arr )¶指向函数的指针,该函数从指向的n
元素arr
开始检索最大元素的索引data
。此功能要求内存段是连续的并且运行正常。返回值始终为0。在中返回最大元素的索引
max_ind
。
dotfunc
( void *的 IP1,npy_intp IS1,无效* IP2,npy_intp IS2,无效* 运算,npy_intp Ñ,无效* ARR )¶指向将两个n
长度的序列相乘的函数的指针,将它们相加,然后将结果放在由指向的元素op
中arr
。ip1
和指向两个序列的开头ip2
。要到达每个序列中的下一个元素,需要分别跳转is1
和is2
个字节。此功能需要正常运行的(尽管不一定是连续的)内存。
scanfunc
( FILE * fd,void * ip,void * arr )¶指向一个函数的指针,该函数从文件描述符中将相应类型的一个元素扫描(scanf样式)fd
到指向的数组内存中ip
。假定该数组是行为正常的。最后一个参数arr
是要扫描到的数组。返回成功分配的接收参数的数量(如果在分配第一个接收参数之前发生匹配失败,则为零);如果返回的值在分配第一个接收参数之前发生,则返回EOF。应该在不持有Python GIL的情况下调用此函数,并且必须抓住它进行错误报告。
fromstr
( char * str,void * ip,char ** endptr,void * arr )¶指向将指针所指向的字符串转换为str
相应类型的一个元素并将其放置在指针所指向的内存位置的函数的指针
ip
。转换完成后,*endptr
指向字符串的其余部分。最后一个参数arr
是ip指向的数组(可变大小数据类型需要)。成功返回0,失败则返回-1。需要一个行为良好的数组。应该在不持有Python GIL的情况下调用此函数,并且必须抓住它进行错误报告。
nonzero
( void * data,void * arr )¶如果由arr
指向的项目data
为非零,则指向返回TRUE的函数的指针
。此函数可以处理行为异常的数组。
fill
( void * data,npy_intp length,void * arr )¶指向函数的指针,该函数用数据填充给定长度的连续数组。数组的前两个元素必须已经填充。将从这两个值中计算出一个增量,并通过重复添加此计算出的增量来计算从第3项到最后一个值。数据缓冲区必须行为良好。
fillwithscalar
( void * 缓冲区,npy_intp 长度,void * 值,void * arr )¶指向一个函数的指针,该函数用buffer
给定地址length
的单个标量填充给定的连续量value
。最后一个参数是获取可变长度数组的项大小所需的数组。
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 )¶指向此数据类型的排序算法的函数指针数组。可以使用与排序相同的排序算法。返回产生排序的索引
result
(必须使用索引0到0进行初始化
length-1
)。
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 )