Python types and C-structures#
Several new types are defined in the C-code. Most of these areaccessible from Python, but a few are not exposed due to their limiteduse. Every new Python type has an associatedPyObject* with aninternal structure that includes a pointer to a “method table” thatdefines how the new object behaves in Python. When you receive aPython object into C code, you always get a pointer to aPyObject
structure. Because aPyObject
structure isvery generic and defines onlyPyObject_HEAD
, by itself itis not very interesting. However, different objects contain moredetails after thePyObject_HEAD
(but you have to cast to thecorrect type to access them — or use accessor functions or macros).
New Python types defined#
Python types are the functional equivalent in C of classes in Python.By constructing a new Python type you make available a new object forPython. The ndarray object is an example of a new type defined in C.New types are defined in C by two basic steps:
creating a C-structure (usually named
Py{Name}Object
) that isbinary- compatible with thePyObject
structure itself but holdsthe additional information needed for that particular object;populating the
PyTypeObject
table (pointed to by the ob_typemember of thePyObject
structure) with pointers to functionsthat implement the desired behavior for the type.
Instead of special method names which define behavior for Pythonclasses, there are “function tables” which point to functions thatimplement the desired results. The PyTypeObject itself is dynamicwhich allows C types that can be “sub-typed” from other C-types in C,and sub-classed in Python. The children types inherit the attributesand methods from their parent(s).
There are two major new types: the ndarray (PyArray_Type
)and the ufunc (PyUFunc_Type
). Additional types play asupportive role: thePyArrayIter_Type
, thePyArrayMultiIter_Type
, and thePyArrayDescr_Type
. ThePyArrayIter_Type
is the type for a flat iterator for anndarray (the object that is returned when getting the flatattribute). ThePyArrayMultiIter_Type
is the type of theobject returned when callingbroadcast
. It handles iteration andbroadcasting over a collection of nested sequences. Also, thePyArrayDescr_Type
is the data-type-descriptor type whoseinstances describe the data andPyArray_DTypeMeta
is themetaclass for data-type descriptors. There are also new scalar-arraytypes which are new Python scalars corresponding to each of thefundamental data types available for arrays. Additional types areplaceholders that allow the array scalars to fit into a hierarchy ofactual Python types. Finally, thePyArray_DTypeMeta
instancescorresponding to the NumPy built-in data types are also publiclyvisible.
PyArray_Type and PyArrayObject#
- PyTypeObjectPyArray_Type#
The Python type of the ndarray is
PyArray_Type
. In C, everyndarray is a pointer to aPyArrayObject
structure. The ob_typemember of this structure contains a pointer to thePyArray_Type
typeobject.
- typePyArrayObject#
- typeNPY_AO#
The
PyArrayObject
C-structure contains all of the requiredinformation for an array. All instances of an ndarray (and itssubclasses) will have this structure. For future compatibility,these structure members should normally be accessed using theprovided macros. If you need a shorter name, then you can make useofNPY_AO
(deprecated) which is defined to be equivalent toPyArrayObject
. Direct access to the struct fields aredeprecated. Use thePyArray_*(arr)
form instead.As of NumPy 1.20, the size of this struct is not considered part ofthe NumPy ABI (see note at the end of the member list).typedefstructPyArrayObject{PyObject_HEADchar*data;intnd;npy_intp*dimensions;npy_intp*strides;PyObject*base;PyArray_Descr*descr;intflags;PyObject*weakreflist;/* version dependent private members */}PyArrayObject;
PyObject_HEAD
This is needed by all Python objects. It consists of (at least)a reference count member (
ob_refcnt
) and a pointer to thetypeobject (ob_type
). (Other elements may also be presentif Python was compiled with special options seeInclude/object.h in the Python source tree for moreinformation). The ob_type member points to a Python typeobject.
- char*data#
Accessible via
PyArray_DATA
, this data member is apointer to the first element of the array. This pointer can(and normally should) be recast to the data type of the array.
- intnd#
An integer providing the number of dimensions for thisarray. When nd is 0, the array is sometimes called a rank-0array. Such arrays have undefined dimensions and strides andcannot be accessed. Macro
PyArray_NDIM
defined inndarraytypes.h
points to this data member.NPY_MAXDIMS
is defined as a compile time constant limiting thenumber of dimensions. This number is 64 since NumPy 2 and was 32before. However, we may wish to remove this limitations in the futureso that it is best to explicitly check dimensionality for codethat relies on such an upper bound.
- npy_intp*dimensions#
An array of integers providing the shape in each dimension aslong as nd\(\geq\) 1. The integer is always large enoughto hold a pointer on the platform, so the dimension size isonly limited by memory.
PyArray_DIMS
is the macroassociated with this data member.
- npy_intp*strides#
An array of integers providing for each dimension the number ofbytes that must be skipped to get to the next element in thatdimension. Associated with macro
PyArray_STRIDES
.
- PyObject*base#
Pointed to by
PyArray_BASE
, this member is used to hold apointer to another Python object that is related to this array.There are two use cases:If this array does not own its own memory, then base points to thePython object that owns it (perhaps another array object)
If this array has the
NPY_ARRAY_WRITEBACKIFCOPY
flag set,then this array is a working copy of a “misbehaved” array.
When
PyArray_ResolveWritebackIfCopy
is called, the array pointed toby base will be updated with the contents of this array.
- PyArray_Descr*descr#
A pointer to a data-type descriptor object (see below). Thedata-type descriptor object is an instance of a new built-intype which allows a generic description of memory. There is adescriptor structure for each data type supported. Thisdescriptor structure contains useful information about the typeas well as a pointer to a table of function pointers toimplement specific functionality. As the name suggests, it isassociated with the macro
PyArray_DESCR
.
- intflags#
Pointed to by the macro
PyArray_FLAGS
, this data member representsthe flags indicating how the memory pointed to by data is to beinterpreted. Possible flags areNPY_ARRAY_C_CONTIGUOUS
,NPY_ARRAY_F_CONTIGUOUS
,NPY_ARRAY_OWNDATA
,NPY_ARRAY_ALIGNED
,NPY_ARRAY_WRITEABLE
,NPY_ARRAY_WRITEBACKIFCOPY
.
- PyObject*weakreflist#
This member allows array objects to have weak references (using theweakref module).
Note
Further members are considered private and version dependent. If the sizeof the struct is important for your code, special care must be taken.A possible use-case when this is relevant is subclassing in C.If your code relies on
sizeof(PyArrayObject)
to be constant,you must add the following check at import time:if(sizeof(PyArrayObject)<PyArray_Type.tp_basicsize){PyErr_SetString(PyExc_ImportError,"Binary incompatibility with NumPy, must recompile/update X.");returnNULL;}
To ensure that your code does not have to be compiled for a specificNumPy version, you may add a constant, leaving room for changes in NumPy.A solution guaranteed to be compatible with any future NumPy versionrequires the use of a runtime calculate offset and allocation size.
ThePyArray_Type
typeobject implements many of the features ofPythonobjects
including thetp_as_number
,tp_as_sequence
,tp_as_mapping
, andtp_as_buffer
interfaces. Therichcomparison
) is also used along with new-style attribute lookup formember (tp_members
) and properties(tp_getset
).ThePyArray_Type
can also be sub-typed.
Tip
Thetp_as_number
methods usea generic approach to call whatever function has been registered forhandling the operation. When the_multiarray_umath
module is imported,it sets the numeric operations for all arrays to the corresponding ufuncs.This choice can be changed withPyUFunc_ReplaceLoopBySignature
.
PyGenericArrType_Type#
- PyTypeObjectPyGenericArrType_Type#
The
PyGenericArrType_Type
is the PyTypeObject definition whichcreate thenumpy.generic
python type.
PyArrayDescr_Type and PyArray_Descr#
- PyTypeObjectPyArrayDescr_Type#
The
PyArrayDescr_Type
is the built-in type of thedata-type-descriptor objects used to describe how the bytes comprisingthe array are to be interpreted. There are 21 statically-definedPyArray_Descr
objects for the built-in data-types. While theseparticipate in reference counting, their reference count should neverreach zero. There is also a dynamic table of user-definedPyArray_Descr
objects that is also maintained. Once adata-type-descriptor object is “registered” it should never bedeallocated either. The functionPyArray_DescrFromType
(…) canbe used to retrieve aPyArray_Descr
object from an enumeratedtype-number (either built-in or user- defined).
- typePyArray_DescrProto#
Identical structure to
PyArray_Descr
. This struct is usedfor static definition of a prototype for registering a new legacyDType byPyArray_RegisterDataType
.See the note in
PyArray_RegisterDataType
for details.
- typePyArray_Descr#
The
PyArray_Descr
structure lies at the heart of thePyArrayDescr_Type
. While it is described here forcompleteness, it should be considered internal to NumPy and manipulated viaPyArrayDescr_*
orPyDataType*
functions and macros. The size of thisstructure is subject to change across versions of NumPy. To ensurecompatibility:Never declare a non-pointer instance of the struct
Never perform pointer arithmetic
Never use
sizeof(PyArray_Descr)
It has the following structure:
typedefstruct{PyObject_HEADPyTypeObject*typeobj;charkind;chartype;charbyteorder;char_former_flags;// unused fieldinttype_num;/* * Definitions after this one must be accessed through accessor * functions (see below) when compiling with NumPy 1.x support. */npy_uint64flags;npy_intpelsize;npy_intpalignment;NpyAuxData*c_metadata;npy_hash_thash;void*reserved_null[2];// unused field, must be NULLed.}PyArray_Descr;
Some dtypes have additional members which are accessible throughPyDataType_NAMES,PyDataType_FIELDS,PyDataType_SUBARRAY, andin some cases (times)PyDataType_C_METADATA.
- PyTypeObject*typeobj#
Pointer to a typeobject that is the corresponding Python type forthe elements of this array. For the builtin types, this points tothe corresponding array scalar. For user-defined types, thisshould point to a user-defined typeobject. This typeobject caneither inherit from array scalars or not. If it does not inheritfrom array scalars, then the
NPY_USE_GETITEM
andNPY_USE_SETITEM
flags should be set in theflags
member.
- charkind#
A character code indicating the kind of array (using the arrayinterface typestring notation). A ‘b’ represents Boolean, a ‘i’represents signed integer, a ‘u’ represents unsigned integer, ‘f’represents floating point, ‘c’ represents complex floating point, ‘S’represents 8-bit zero-terminated bytes, ‘U’ represents 32-bit/characterunicode string, and ‘V’ represents arbitrary.
- chartype#
A traditional character code indicating the data type.
- charbyteorder#
A character indicating the byte-order: ‘>’ (big-endian), ‘<’ (little-endian), ‘=’ (native), ‘|’ (irrelevant, ignore). All builtin data-types have byteorder ‘=’.
- npy_uint64flags#
A data-type bit-flag that determines if the data-type exhibits object-array like behavior. Each bit in this member is a flag which are namedas:
- inttype_num#
A number that uniquely identifies the data type. For new data-types,this number is assigned when the data-type is registered.
- npy_intpelsize#
For data types that are always the same size (such as long), thisholds the size of the data type. For flexible data types wheredifferent arrays can have a different elementsize, this should be0.
SeePyDataType_ELSIZE andPyDataType_SET_ELSIZE for a way to accessthis field in a NumPy 1.x compatible way.
- npy_intpalignment#
A number providing alignment information for this data type.Specifically, it shows how far from the start of a 2-elementstructure (whose first element is a
char
), the compilerplaces an item of this type:offsetof(struct{charc;typev;},v)
SeePyDataType_ALIGNMENT for a way to access this field in a NumPy 1.xcompatible way.
- NpyAuxData*c_metadata#
Metadata specific to the C implementationof the particular dtype. Added for NumPy 1.7.0.
- typenpy_hash_t#
- npy_hash_t*hash#
Used for caching hash values.
- NPY_ITEM_REFCOUNT#
Indicates that items of this data-type must be referencecounted (using
Py_INCREF
andPy_DECREF
).
- NPY_ITEM_HASOBJECT#
Same as
NPY_ITEM_REFCOUNT
.
- NPY_LIST_PICKLE#
Indicates arrays of this data-type must be converted to a listbefore pickling.
- NPY_ITEM_IS_POINTER#
Indicates the item is a pointer to some other data-type
- NPY_NEEDS_INIT#
Indicates memory for this data-type must be initialized (setto 0) on creation.
- NPY_NEEDS_PYAPI#
Indicates this data-type requires the Python C-API duringaccess (so don’t give up the GIL if array access is going tobe needed).
- NPY_USE_GETITEM#
On array access use the
f->getitem
function pointerinstead of the standard conversion to an array scalar. Mustuse if you don’t define an array scalar to go along withthe data-type.
- NPY_USE_SETITEM#
When creating a 0-d array from an array scalar use
f->setitem
instead of the standard copy from an arrayscalar. Must use if you don’t define an array scalar to goalong with the data-type.
- NPY_FROM_FIELDS#
The bits that are inherited for the parent data-type if thesebits are set in any field of the data-type. Currently (
NPY_NEEDS_INIT
|NPY_LIST_PICKLE
|NPY_ITEM_REFCOUNT
|NPY_NEEDS_PYAPI
).
- NPY_OBJECT_DTYPE_FLAGS#
Bits set for the object data-type: (
NPY_LIST_PICKLE
|NPY_USE_GETITEM
|NPY_ITEM_IS_POINTER
|NPY_ITEM_REFCOUNT
|NPY_NEEDS_INIT
|NPY_NEEDS_PYAPI
).
- intPyDataType_FLAGCHK(PyArray_Descr*dtype,intflags)#
Return true if all the given flags are set for the data-typeobject.
- intPyDataType_REFCHK(PyArray_Descr*dtype)#
Equivalent to
PyDataType_FLAGCHK
(dtype,NPY_ITEM_REFCOUNT
).
PyArray_ArrFuncs#
- PyArray_ArrFuncs*PyDataType_GetArrFuncs(PyArray_Descr*dtype)#
Fetch the legacyPyArray_ArrFuncs of the datatype (cannot fail).
New in version NumPy:2.0This function was added in a backwards compatible and backportableway in NumPy 2.0 (see
npy_2_compat.h
).Any code that previously accessed the->f
slot of thePyArray_Descr
, must now use this function and backport it tocompile with 1.x.(Thenpy_2_compat.h
header can be vendored for this purpose.)
- typePyArray_ArrFuncs#
Functions implementing internal features. Not all of thesefunction pointers must be defined for a given type. The requiredmembers are
nonzero
,copyswap
,copyswapn
,setitem
,getitem
, andcast
. These are assumed to be non-NULL
andNULL
entries will cause a program crash. The otherfunctions may beNULL
which will just mean reducedfunctionality for that data-type. (Also, the nonzero function willbe filled in with a default function if it isNULL
when youregister a user-defined data-type).typedefstruct{PyArray_VectorUnaryFunc*cast[NPY_NTYPES_LEGACY];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;void*_unused1;void*_unused2;void*_unused3;PyArray_ArgFunc*argmin;}PyArray_ArrFuncs;
The concept of a behaved segment is used in the description of thefunction pointers. A behaved segment is one that is aligned and innative machine byte-order for the data-type. The
nonzero
,copyswap
,copyswapn
,getitem
, andsetitem
functions can (and must) deal with mis-behaved arrays. The otherfunctions require behaved memory segments.Note
The functions are largely legacy API, however, some are still used.As of NumPy 2.x they are only available viaPyDataType_GetArrFuncs(see the function for more details).Before using any function defined in the struct you should checkwhether it is
NULL
. In general, the functionsgetitem
,setitem
,copyswap
, andcopyswapn
can be expected to bedefined, but all functions are expected to be replaced with newer API.For example,PyArray_Pack
is a more powerful version ofsetitem
that for example correctly deals with casts.- voidcast(void*from,void*to,npy_intpn,void*fromarr,void*toarr)#
An array of function pointers to cast from the current type toall of the other builtin types. Each function casts acontiguous, aligned, and notswapped buffer pointed at byfrom to a contiguous, aligned, and notswapped buffer pointedat byto The number of items to cast is given byn, andthe argumentsfromarr andtoarr are interpreted asPyArrayObjects for flexible arrays to get itemsizeinformation.
- PyObject*getitem(void*data,void*arr)#
A pointer to a function that returns a standard Python objectfrom a single element of the array objectarr pointed to bydata. This function must be able to deal with “misbehaved“(misaligned and/or swapped) arrays correctly.
- intsetitem(PyObject*item,void*data,void*arr)#
A pointer to a function that sets the Python objectiteminto the array,arr, at the position pointed to bydata. This function deals with “misbehaved” arrays. If successful,a zero is returned, otherwise, a negative one is returned (anda Python error set).
- voidcopyswap(void*dest,void*src,intswap,void*arr)#
These members are both pointers to functions to copy data fromsrc todest andswap if indicated. The value of arr isonly used for flexible (
NPY_STRING
,NPY_UNICODE
,andNPY_VOID
) arrays (and is obtained fromarr->descr->elsize
). The second function copies a singlevalue, while the first loops over n values with the providedstrides. These functions can deal with misbehavedsrcdata. Ifsrc is NULL then no copy is performed. Ifswap is0, then no byteswapping occurs. It is assumed thatdest andsrc do not overlap. If they overlap, then usememmove
(…) first followed bycopyswap(n)
with NULL valuedsrc
.
- intcompare(constvoid*d1,constvoid*d2,void*arr)#
A pointer to a function that compares two elements of thearray,
arr
, pointed to byd1
andd2
. Thisfunction requires behaved (aligned and not swapped) arrays.The return value is 1 if *d1
> *d2
, 0 if *d1
== *d2
, and -1 if *d1
< *d2
. The array objectarr
isused to retrieve itemsize and field information for flexible arrays.
- intargmax(void*data,npy_intpn,npy_intp*max_ind,void*arr)#
A pointer to a function that retrieves the index of thelargest of
n
elements inarr
beginning at the elementpointed to bydata
. This function requires that thememory segment be contiguous and behaved. The return value isalways 0. The index of the largest element is returned inmax_ind
.
- voiddotfunc(void*ip1,npy_intpis1,void*ip2,npy_intpis2,void*op,npy_intpn,void*arr)#
A pointer to a function that multiplies two
n
-lengthsequences together, adds them, and places the result inelement pointed to byop
ofarr
. The start of the twosequences are pointed to byip1
andip2
. To get tothe next element in each sequence requires a jump ofis1
andis2
bytes, respectively. This function requiresbehaved (though not necessarily contiguous) memory.
- intscanfunc(FILE*fd,void*ip,void*arr)#
A pointer to a function that scans (scanf style) one elementof the corresponding type from the file descriptor
fd
intothe array memory pointed to byip
. The array is assumedto be behaved.The last argumentarr
is the array to be scanned into.Returns number of receiving arguments successfully assigned (whichmay be zero in case a matching failure occurred before the firstreceiving argument was assigned), or EOF if input failure occursbefore the first receiving argument was assigned.This function should be called without holding the Python GIL, andhas to grab it for error reporting.
- intfromstr(char*str,void*ip,char**endptr,void*arr)#
A pointer to a function that converts the string pointed to by
str
to one element of the corresponding type and places itin the memory location pointed to byip
. After theconversion is completed,*endptr
points to the rest of thestring. The last argumentarr
is the array into which ippoints (needed for variable-size data- types). Returns 0 onsuccess or -1 on failure. Requires a behaved array.This function should be called without holding the Python GIL, andhas to grab it for error reporting.
- npy_boolnonzero(void*data,void*arr)#
A pointer to a function that returns TRUE if the item of
arr
pointed to bydata
is nonzero. This function candeal with misbehaved arrays.
- voidfill(void*data,npy_intplength,void*arr)#
A pointer to a function that fills a contiguous array of givenlength with data. The first two elements of the array mustalready be filled- in. From these two values, a delta will becomputed and the values from item 3 to the end will becomputed by repeatedly adding this computed delta. The databuffer must be well-behaved.
- voidfillwithscalar(void*buffer,npy_intplength,void*value,void*arr)#
A pointer to a function that fills a contiguous
buffer
ofthe givenlength
with a single scalarvalue
whoseaddress is given. The final argument is the array which isneeded to get the itemsize for variable-length arrays.
- intsort(void*start,npy_intplength,void*arr)#
An array of function pointers to a particular sortingalgorithms. A particular sorting algorithm is obtained using akey (so far
NPY_QUICKSORT
,NPY_HEAPSORT
,andNPY_MERGESORT
are defined). These sorts are donein-place assuming contiguous and aligned data.
- intargsort(void*start,npy_intp*result,npy_intplength,void*arr)#
An array of function pointers to sorting algorithms for thisdata type. The same sorting algorithms as for sort areavailable. The indices producing the sort are returned in
result
(which must be initialized with indices 0 tolength-1
inclusive).
- PyObject*castdict#
Either
NULL
or a dictionary containing low-level castingfunctions for user- defined data-types. Each function iswrapped in aPyCapsule* and keyed bythe data-type number.
- NPY_SCALARKINDscalarkind(PyArrayObject*arr)#
A function to determine how scalars of this type should beinterpreted. The argument is
NULL
or a 0-dimensional arraycontaining the data (if that is needed to determine the kindof scalar). The return value must be of typeNPY_SCALARKIND
.
- int**cancastscalarkindto#
Either
NULL
or an array ofNPY_NSCALARKINDS
pointers. These pointers should each be eitherNULL
or apointer to an array of integers (terminated byNPY_NOTYPE
) indicating data-types that a scalar ofthis data-type of the specified kind can be cast to safely(this usually means without losing precision).
- int*cancastto#
Either
NULL
or an array of integers (terminated byNPY_NOTYPE
) indicated data-types that this data-typecan be cast to safely (this usually means without losingprecision).
- intargmin(void*data,npy_intpn,npy_intp*min_ind,void*arr)#
A pointer to a function that retrieves the index of thesmallest of
n
elements inarr
beginning at the elementpointed to bydata
. This function requires that thememory segment be contiguous and behaved. The return value isalways 0. The index of the smallest element is returned inmin_ind
.
- voidcast(void*from,void*to,npy_intpn,void*fromarr,void*toarr)#
PyArrayMethod_Context and PyArrayMethod_Spec#
- typePyArrayMethodObject_tag#
An opaque struct used to represent the method “self” in ArrayMethod loops.
- typePyArrayMethod_Context#
A struct that is passed in to ArrayMethod loops to provide context for theruntime usage of the loop.
typedefstruct{PyObject*caller;structPyArrayMethodObject_tag*method;PyArray_Descr*const*descriptors;}PyArrayMethod_Context
- PyObject*caller#
The caller, which is typically the ufunc that called the loop. May be
NULL
when a call is not from a ufunc (e.g. casts).
- structPyArrayMethodObject_tag*method#
The method “self”. Currently this object is an opaque pointer.
- PyArray_Descr**descriptors#
An array of descriptors for the ufunc loop, filled in by
resolve_descriptors
. The length of the array isnin
+nout
.
- PyObject*caller#
- typePyArrayMethod_Spec#
A struct used to register an ArrayMethod with NumPy. We use the slotsmechanism used by the Python limited API. See below for the slot definitions.
typedefstruct{constchar*name;intnin,nout;NPY_CASTINGcasting;NPY_ARRAYMETHOD_FLAGSflags;PyArray_DTypeMeta**dtypes;PyType_Slot*slots;}PyArrayMethod_Spec;
- constchar*name#
The name of the loop.
- intnin#
The number of input operands
- intnout#
The number of output operands.
- NPY_CASTINGcasting#
Used to indicate how minimally permissive a casting operation shouldbe. For example, if a cast operation might in some circumstances be safe,but in others unsafe, then
NPY_UNSAFE_CASTING
should be set. Not usedfor ufunc loops but must still be set.
- NPY_ARRAYMETHOD_FLAGSflags#
The flags set for the method.
- PyArray_DTypeMeta**dtypes#
The DTypes for the loop. Must be
nin
+nout
in length.
- PyType_Slot*slots#
An array of slots for the method. Slot IDs must be one of the valuesbelow.
- constchar*name#
PyArray_DTypeMeta and PyArrayDTypeMeta_Spec#
- PyTypeObjectPyArrayDTypeMeta_Type#
The python type object corresponding to
PyArray_DTypeMeta
.
- typePyArray_DTypeMeta#
A largely opaque struct representing DType classes. Each instance defines ametaclass for a single NumPy data type. Data types can either benon-parametric or parametric. For non-parametric types, the DType class hasa one-to-one correspondence with the descriptor instance created from theDType class. Parametric types can correspond to many different dtypeinstances depending on the chosen parameters. This type is available in thepublic
numpy/dtype_api.h
header. Currently use of this struct is notsupported in the limited CPython API, so ifPy_LIMITED_API
is set, thistype is a typedef forPyTypeObject
.typedefstruct{PyHeapTypeObjectsuper;PyArray_Descr*singleton;inttype_num;PyTypeObject*scalar_type;npy_uint64flags;void*dt_slots;void*reserved[3];}PyArray_DTypeMeta
- PyHeapTypeObjectsuper#
The superclass, providing hooks into the python objectAPI. Set members of this struct to fill in the functionsimplementing the
PyTypeObject
API (e.g.tp_new
).
- PyArray_Descr*singleton#
A descriptor instance suitable for use as a singletondescriptor for the data type. This is useful fornon-parametric types representing simple plain old data typewhere there is only one logical descriptor instance for alldata of the type. Can be NULL if a singleton instance is notappropriate.
- inttype_num#
Corresponds to the type number for legacy data types. Datatypes defined outside of NumPy and possibly future data typesshipped with NumPy will have
type_num
set to -1, so thisshould not be relied on to discriminate between data types.
- PyTypeObject*scalar_type#
The type of scalar instances for this data type.
- npy_uint64flags#
Flags can be set to indicate to NumPy that this data typehas optional behavior. SeeFlags for a listing ofallowed flag values.
- void*dt_slots#
An opaque pointer to a private struct containingimplementations of functions in the DType API. This is filledin from the
slots
member of thePyArrayDTypeMeta_Spec
instance used to initialize the DType.
- PyHeapTypeObjectsuper#
- typePyArrayDTypeMeta_Spec#
A struct used to initialize a new DType with the
PyArrayInitDTypeMeta_FromSpec
function.typedefstruct{PyTypeObject*typeobj;intflags;PyArrayMethod_Spec**casts;PyType_Slot*slots;PyTypeObject*baseclass;}
- PyTypeObject*typeobj#
Either
NULL
or the type of the python scalar associated withthe DType. Scalar indexing into an array returns an item with thistype.
- intflags#
Static flags for the DType class, indicating whether the DType isparametric, abstract, or represents numeric data. The latter isoptional but is useful to set to indicate to downstream code ifthe DType represents data that are numbers (ints, floats, or othernumeric data type) or something else (e.g. a string, unit, ordate).
- PyArrayMethod_Spec**casts;#
A
NULL
-terminated array of ArrayMethod specifications forcasts defined by the DType.
- PyType_Slot*slots;#
A
NULL
-terminated array of slot specifications for implementationsof functions in the DType API. Slot IDs must be one of theDType slot IDs enumerated inSlot IDs and API Function Typedefs.
- PyTypeObject*typeobj#
Exposed DTypes classes (PyArray_DTypeMeta
objects)#
For use with promoters, NumPy exposes a number of Dtypes following thepatternPyArray_<Name>DType
corresponding to those found innp.dtypes.
Additionally, the three DTypes,PyArray_PyLongDType
,PyArray_PyFloatDType
,PyArray_PyComplexDType
correspond to thePython scalar values. These cannot be used in all places, but do allowfor example the common dtype operation and implementing promotion with themmay be necessary.
Further, the following abstract DTypes are defined which cover both thebuiltin NumPy ones and the python ones, and users can in principle subclassfrom them (this does not inherit any DType specific functionality):*PyArray_IntAbstractDType
*PyArray_FloatAbstractDType
*PyArray_ComplexAbstractDType
Warning
As of NumPy 2.0, theonly valid use for these DTypes is registering apromoter conveniently to e.g. match “any integers” (and subclass checks).Because of this, they are not exposed to Python.
PyUFunc_Type and PyUFuncObject#
- PyTypeObjectPyUFunc_Type#
The ufunc object is implemented by creation of the
PyUFunc_Type
. It is a very simple type that implements onlybasic getattribute behavior, printing behavior, and has callbehavior which allows these objects to act like functions. Thebasic idea behind the ufunc is to hold a reference to fast1-dimensional (vector) loops for each data type that supports theoperation. These one-dimensional loops all have the same signatureand are the key to creating a new ufunc. They are called by thegeneric looping code as appropriate to implement the N-dimensionalfunction. There are also some generic 1-d loops defined forfloating and complexfloating arrays that allow you to define aufunc using a single scalar function (e.g. atanh).
- typePyUFuncObject#
The core of the ufunc is the
PyUFuncObject
which contains allthe information needed to call the underlying C-code loops thatperform the actual work. While it is described here for completeness, itshould be considered internal to NumPy and manipulated viaPyUFunc_*
functions. The size of this structure is subject to change across versionsof NumPy. To ensure compatibility:Never declare a non-pointer instance of the struct
Never perform pointer arithmetic
Never use
sizeof(PyUFuncObject)
It has the following structure:
typedefstruct{PyObject_HEADintnin;intnout;intnargs;intidentity;PyUFuncGenericFunction*functions;void**data;intntypes;intreserved1;constchar*name;char*types;constchar*doc;void*ptr;PyObject*obj;PyObject*userloops;intcore_enabled;intcore_num_dim_ix;int*core_num_dims;int*core_dim_ixs;int*core_offsets;char*core_signature;PyUFunc_TypeResolutionFunc*type_resolver;void*reserved2;void*reserved3;npy_uint32*op_flags;npy_uint32*iter_flags;/* new in API version 0x0000000D */npy_intp*core_dim_sizes;npy_uint32*core_dim_flags;PyObject*identity_value;/* Further private slots (size depends on the NumPy version) */}PyUFuncObject;
- intnin#
The number of input arguments.
- intnout#
The number of output arguments.
- intnargs#
The total number of arguments (nin +nout). This must beless than
NPY_MAXARGS
.
- intidentity#
Either
PyUFunc_One
,PyUFunc_Zero
,PyUFunc_MinusOne
,PyUFunc_None
,PyUFunc_ReorderableNone
, orPyUFunc_IdentityValue
to indicatethe identity for this operation. It is only used for areduce-like call on an empty array.
- voidfunctions(char**args,npy_intp*dims,npy_intp*steps,void*extradata)#
An array of function pointers — one for each data typesupported by the ufunc. This is the vector loop that is calledto implement the underlying functiondims [0] times. Thefirst argument,args, is an array ofnargs pointers tobehaved memory. Pointers to the data for the input argumentsare first, followed by the pointers to the data for the outputarguments. How many bytes must be skipped to get to the nextelement in the sequence is specified by the corresponding entryin thesteps array. The last argument allows the loop toreceive extra information. This is commonly used so that asingle, generic vector loop can be used for multiplefunctions. In this case, the actual scalar function to call ispassed in asextradata. The size of this function pointerarray is ntypes.
- void**data#
Extra data to be passed to the 1-d vector loops or
NULL
ifno extra-data is needed. This C-array must be the same size (i.e. ntypes) as the functions array.NULL
is used ifextra_data is not needed. Several C-API calls for UFuncs arejust 1-d vector loops that make use of this extra data toreceive a pointer to the actual function to call.
- intntypes#
The number of supported data types for the ufunc. This numberspecifies how many different 1-d loops (of the builtin datatypes) are available.
- char*name#
A string name for the ufunc. This is used dynamically to buildthe __doc__ attribute of ufuncs.
- char*types#
An array of\(nargs \times ntypes\) 8-bit type_numberswhich contains the type signature for the function for each ofthe supported (builtin) data types. For each of thentypesfunctions, the corresponding set of type numbers in this arrayshows how theargs argument should be interpreted in the 1-dvector loop. These type numbers do not have to be the same typeand mixed-type ufuncs are supported.
- char*doc#
Documentation for the ufunc. Should not contain the functionsignature as this is generated dynamically when __doc__ isretrieved.
- void*ptr#
Any dynamically allocated memory. Currently, this is used fordynamic ufuncs created from a python function to store room forthe types, data, and name members.
- PyObject*obj#
For ufuncs dynamically created from python functions, this memberholds a reference to the underlying Python function.
- PyObject*userloops#
A dictionary of user-defined 1-d vector loops (stored as CObjectptrs) for user-defined types. A loop may be registered by theuser for any user-defined type. It is retrieved by type number.User defined type numbers are always larger than
NPY_USERDEF
.
- intcore_enabled#
0 for scalar ufuncs; 1 for generalized ufuncs
- intcore_num_dim_ix#
Number of distinct core dimension names in the signature
- int*core_num_dims#
Number of core dimensions of each argument
- int*core_dim_ixs#
Dimension indices in a flattened form; indices of argument
k
arestored incore_dim_ixs[core_offsets[k]:core_offsets[k]+core_numdims[k]]
- int*core_offsets#
Position of 1st core dimension of each argument in
core_dim_ixs
,equivalent to cumsum(core_num_dims
)
- char*core_signature#
Core signature string
- PyUFunc_TypeResolutionFunc*type_resolver#
A function which resolves the types and fills an array with the dtypesfor the inputs and outputs
- typePyUFunc_TypeResolutionFunc#
The function pointer type for
type_resolver
- typePyUFunc_TypeResolutionFunc#
- npy_uint32op_flags#
Override the default operand flags for each ufunc operand.
- npy_uint32iter_flags#
Override the default nditer flags for the ufunc.
Added in API version 0x0000000D
- npy_intp*core_dim_sizes#
For each distinct core dimension, the possiblefrozen size if
UFUNC_CORE_DIM_SIZE_INFERRED
is0
- npy_uint32*core_dim_flags#
For each distinct core dimension, a set of flags (
UFUNC_CORE_DIM_CAN_IGNORE
andUFUNC_CORE_DIM_SIZE_INFERRED
)
- PyObject*identity_value#
Identity for reduction, when
PyUFuncObject.identity
is equal toPyUFunc_IdentityValue
.
- UFUNC_CORE_DIM_CAN_IGNORE#
if the dim name ends in
?
PyArrayIter_Type and PyArrayIterObject#
- PyTypeObjectPyArrayIter_Type#
This is an iterator object that makes it easy to loop over anN-dimensional array. It is the object returned from the flatattribute of an ndarray. It is also used extensively throughout theimplementation internals to loop over an N-dimensional array. Thetp_as_mapping interface is implemented so that the iterator objectcan be indexed (using 1-d indexing), and a few methods areimplemented through the tp_methods table. This object implements thenext method and can be used anywhere an iterator can be used inPython.
- typePyArrayIterObject#
The C-structure corresponding to an object of
PyArrayIter_Type
isthePyArrayIterObject
. ThePyArrayIterObject
is used tokeep track of a pointer into an N-dimensional array. It contains associatedinformation used to quickly march through the array. The pointer canbe adjusted in three basic ways: 1) advance to the “next” position inthe array in a C-style contiguous fashion, 2) advance to an arbitraryN-dimensional coordinate in the array, and 3) advance to an arbitraryone-dimensional index into the array. The members of thePyArrayIterObject
structure are used in thesecalculations. Iterator objects keep their own dimension and stridesinformation about an array. This can be adjusted as needed for“broadcasting,” or to loop over only specific dimensions.typedefstruct{PyObject_HEADintnd_m1;npy_intpindex;npy_intpsize;npy_intpcoordinates[NPY_MAXDIMS_LEGACY_ITERS];npy_intpdims_m1[NPY_MAXDIMS_LEGACY_ITERS];npy_intpstrides[NPY_MAXDIMS_LEGACY_ITERS];npy_intpbackstrides[NPY_MAXDIMS_LEGACY_ITERS];npy_intpfactors[NPY_MAXDIMS_LEGACY_ITERS];PyArrayObject*ao;char*dataptr;npy_boolcontiguous;}PyArrayIterObject;
- intnd_m1#
\(N-1\) where\(N\) is the number of dimensions in theunderlying array.
- npy_intp*strides#
The strides of the array. How many bytes needed to jump to the nextelement in each dimension.
- npy_intp*backstrides#
How many bytes needed to jump from the end of a dimension backto its beginning. Note that
backstrides[k]==strides[k]*dims_m1[k]
, but it is stored here as an optimization.
- npy_intp*factors#
This array is used in computing an N-d index from a 1-d index. Itcontains needed products of the dimensions.
- PyArrayObject*ao#
A pointer to the underlying ndarray this iterator was created torepresent.
- char*dataptr#
This member points to an element in the ndarray indicated by theindex.
- npy_boolcontiguous#
This flag is true if the underlying array is
NPY_ARRAY_C_CONTIGUOUS
. It is used to simplifycalculations when possible.
- intnd_m1#
How to use an array iterator on a C-level is explained more fully inlater sections. Typically, you do not need to concern yourself withthe internal structure of the iterator object, and merely interactwith it through the use of the macrosPyArray_ITER_NEXT
(it),PyArray_ITER_GOTO
(it, dest), orPyArray_ITER_GOTO1D
(it, index). All of these macros require the argumentit to be aPyArrayIterObject*.
PyArrayMultiIter_Type and PyArrayMultiIterObject#
- PyTypeObjectPyArrayMultiIter_Type#
This type provides an iterator that encapsulates the concept ofbroadcasting. It allows\(N\) arrays to be broadcast togetherso that the loop progresses in C-style contiguous fashion over thebroadcasted array. The corresponding C-structure is the
PyArrayMultiIterObject
whose memory layout must begin anyobject,obj, passed in to thePyArray_Broadcast
(obj)function. Broadcasting is performed by adjusting array iterators sothat each iterator represents the broadcasted shape and size, buthas its strides adjusted so that the correct element from the arrayis used at each iteration.
- typePyArrayMultiIterObject#
typedefstruct{PyObject_HEADintnumiter;npy_intpsize;npy_intpindex;intnd;npy_intpdimensions[NPY_MAXDIMS_LEGACY_ITERS];PyArrayIterObject*iters[];}PyArrayMultiIterObject;
- intnumiter#
The number of arrays that need to be broadcast to the same shape.
- intnd#
The number of dimensions in the broadcasted result.
- PyArrayIterObject**iters#
An array of iterator objects that holds the iterators for thearrays to be broadcast together. On return, the iterators areadjusted for broadcasting.
- intnumiter#
PyArrayNeighborhoodIter_Type and PyArrayNeighborhoodIterObject#
- PyTypeObjectPyArrayNeighborhoodIter_Type#
This is an iterator object that makes it easy to loop over anN-dimensional neighborhood.
- typePyArrayNeighborhoodIterObject#
The C-structure corresponding to an object of
PyArrayNeighborhoodIter_Type
is thePyArrayNeighborhoodIterObject
.typedefstruct{PyObject_HEADintnd_m1;npy_intpindex,size;npy_intpcoordinates[NPY_MAXDIMS_LEGACY_ITERS]npy_intpdims_m1[NPY_MAXDIMS_LEGACY_ITERS];npy_intpstrides[NPY_MAXDIMS_LEGACY_ITERS];npy_intpbackstrides[NPY_MAXDIMS_LEGACY_ITERS];npy_intpfactors[NPY_MAXDIMS_LEGACY_ITERS];PyArrayObject*ao;char*dataptr;npy_boolcontiguous;npy_intpbounds[NPY_MAXDIMS_LEGACY_ITERS][2];npy_intplimits[NPY_MAXDIMS_LEGACY_ITERS][2];npy_intplimits_sizes[NPY_MAXDIMS_LEGACY_ITERS];npy_iter_get_dataptr_ttranslate;npy_intpnd;npy_intpdimensions[NPY_MAXDIMS_LEGACY_ITERS];PyArrayIterObject*_internal_iter;char*constant;intmode;}PyArrayNeighborhoodIterObject;
ScalarArrayTypes#
There is a Python type for each of the different built-in data typesthat can be present in the array. Most of these are simple wrappersaround the corresponding data type in C. The C-names for these typesarePy{TYPE}ArrType_Type
where{TYPE}
can be
Bool,Byte,Short,Int,Long,LongLong,UByte,UShort,UInt,ULong,ULongLong,Half,Float,Double,LongDouble,CFloat,CDouble,CLongDouble,String,Unicode,Void,Datetime,Timedelta, andObject.
These type names are part of the C-API and can therefore be created inextension C-code. There is also aPyIntpArrType_Type
and aPyUIntpArrType_Type
that are simple substitutes for one of theinteger types that can hold a pointer on the platform. The structureof these scalar objects is not exposed to C-code. The functionPyArray_ScalarAsCtype
(..) can be used to extract the C-typevalue from the array scalar and the functionPyArray_Scalar
(…) can be used to construct an array scalar from a C-value.
Other C-structures#
A few new C-structures were found to be useful in the development ofNumPy. These C-structures are used in at least one C-API call and aretherefore documented here. The main reason these structures weredefined is to make it easy to use the Python ParseTuple C-API toconvert from Python objects to a useful C-Object.
PyArray_Dims#
- typePyArray_Dims#
This structure is very useful when shape and/or strides informationis supposed to be interpreted. The structure is:
typedefstruct{npy_intp*ptr;intlen;}PyArray_Dims;
The members of this structure are
- npy_intp*ptr#
A pointer to a list of (
npy_intp
) integers whichusually represent array shape or array strides.
- intlen#
The length of the list of integers. It is assumed safe toaccessptr [0] toptr [len-1].
- npy_intp*ptr#
PyArray_Chunk#
- typePyArray_Chunk#
This is equivalent to the buffer object structure in Python up tothe ptr member. On 32-bit platforms (i.e. if
NPY_SIZEOF_INT
==NPY_SIZEOF_INTP
), the len member also matches an equivalentmember of the buffer object. It is useful to represent a genericsingle-segment chunk of memory.typedefstruct{PyObject_HEADPyObject*base;void*ptr;npy_intplen;intflags;}PyArray_Chunk;
The members are
- PyObject*base#
The Python object this chunk of memory comes from. Needed so thatmemory can be accounted for properly.
- void*ptr#
A pointer to the start of the single-segment chunk of memory.
- intflags#
Any data flags (e.g.
NPY_ARRAY_WRITEABLE
) that shouldbe used to interpret the memory.
- PyObject*base#
PyArrayInterface#
See also
- typePyArrayInterface#
The
PyArrayInterface
structure is defined so that NumPy andother extension modules can use the rapid array interfaceprotocol. The__array_struct__
method of an object thatsupports the rapid array interface protocol should return aPyCapsule
that contains a pointer to aPyArrayInterface
structure with the relevant details of the array. After the newarray is created, the attribute should beDECREF
’d which willfree thePyArrayInterface
structure. Remember toINCREF
theobject (whose__array_struct__
attribute was retrieved) andpoint the base member of the newPyArrayObject
to this sameobject. In this way the memory for the array will be managedcorrectly.typedefstruct{inttwo;intnd;chartypekind;intitemsize;intflags;npy_intp*shape;npy_intp*strides;void*data;PyObject*descr;}PyArrayInterface;
- inttwo#
the integer 2 as a sanity check.
- intnd#
the number of dimensions in the array.
- chartypekind#
A character indicating what kind of array is present according to thetypestring convention with ‘t’ -> bitfield, ‘b’ -> Boolean, ‘i’ ->signed integer, ‘u’ -> unsigned integer, ‘f’ -> floating point, ‘c’ ->complex floating point, ‘O’ -> object, ‘S’ -> (byte-)string, ‘U’ ->unicode, ‘V’ -> void.
- intitemsize#
The number of bytes each item in the array requires.
- intflags#
Any of the bits
NPY_ARRAY_C_CONTIGUOUS
(1),NPY_ARRAY_F_CONTIGUOUS
(2),NPY_ARRAY_ALIGNED
(0x100),NPY_ARRAY_NOTSWAPPED
(0x200), orNPY_ARRAY_WRITEABLE
(0x400) to indicate something about the data. TheNPY_ARRAY_ALIGNED
,NPY_ARRAY_C_CONTIGUOUS
, andNPY_ARRAY_F_CONTIGUOUS
flags can actually be determined fromthe other parameters. The flagNPY_ARR_HAS_DESCR
(0x800) can also be set to indicate to objects consuming theversion 3 array interface that the descr member of thestructure is present (it will be ignored by objects consumingversion 2 of the array interface).
- npy_intp*strides#
An array containing the number of bytes to jump to get to the nextelement in each dimension.
- void*data#
A pointerto the first element of the array.
- PyObject*descr#
A Python object describing the data-type in more detail (sameas thedescr key in
__array_interface__
). This can beNULL
iftypekind anditemsize provide enoughinformation. This field is also ignored unlessNPY_ARR_HAS_DESCR
flag is on inflags.
- inttwo#
Internally used structures#
Internally, the code uses some additional Python objects primarily formemory management. These types are not accessible directly fromPython, and are not exposed to the C-API. They are included here onlyfor completeness and assistance in understanding the code.
- typePyUFunc_Loop1d#
A simple linked-list of C-structures containing the information neededto define a 1-d loop for a ufunc for every defined signature of auser-defined data-type.
- PyTypeObjectPyArrayMapIter_Type#
Advanced indexing is handled with this Python type. It is simply aloose wrapper around the C-structure containing the variablesneeded for advanced array indexing.
- typePyArrayMapIterObject#
The C-structure associated with
PyArrayMapIter_Type
.This structure is useful if you are trying tounderstand the advanced-index mapping code. It is defined in thearrayobject.h
header. This type is not exposed to Python andcould be replaced with a C-structure. As a Python type it takesadvantage of reference- counted memory management.
NumPy C-API and C complex#
When you use the NumPy C-API, you will have access to complex real declarationsnpy_cdouble
andnpy_cfloat
, which are declared in terms of the Cstandard types fromcomplex.h
. Unfortunately,complex.h
contains#define I …` (where the actual definition depends on the compiler), whichmeans that any downstream user that does#include<numpy/arrayobject.h>
could getI
defined, and using something like declaringdoubleI;
intheir code will result in an obscure compiler error like
This error can be avoided by adding:
#undef I
to your code.
Changed in version 2.0:The inclusion ofcomplex.h
was new in NumPy 2, so that code defininga differentI
may not have required the#undefI
on older versions.NumPy 2.0.1 briefly included the#underI