bundles / numpy latest / docs
Doc
reference:arrays.interface
docs/reference:arrays.interface
The array interface protocol
target__ https://cython.org/target__ https://github.com/cython/cython/wiki/tutorials-numpy- version
3
The array interface (sometimes called array protocol) was created in 2005 as a means for array-like Python objects to reuse each other's data buffers intelligently whenever possible. The homogeneous N-dimensional array interface is a default mechanism for objects to share N-dimensional array memory and information. The interface consists of a Python-side and a C-side using two attributes. Objects wishing to be considered an N-dimensional array in application code should support at least one of these attributes. Objects wishing to support an N-dimensional array in application code should look for at least one of these attributes and use the information provided appropriately.
This interface describes homogeneous arrays in the sense that each item of the array has the same "type". This type can be very simple or it can be a quite arbitrary and complicated C-like structure.
There are two ways to use the interface: A Python side and a C-side. Both are separate attributes.
Python side
This approach to the interface consists of the object having an ~object.__array_interface__ attribute.
C-struct access
This approach to the array interface allows for faster access to an array using only one attribute lookup and a well-defined C-structure.
The PyArrayInterface structure is defined in numpy/ndarrayobject.h as
typedef struct { int two; /* contains the integer 2 -- simple sanity check */ int nd; /* number of dimensions */ char typekind; /* kind in array --- character code of typestr */ int itemsize; /* size of each element */ int flags; /* flags indicating how the data should be interpreted */ /* must set ARR_HAS_DESCR bit to validate descr */ Py_ssize_t *shape; /* A length-nd array of shape information */ Py_ssize_t *strides; /* A length-nd array of stride information */ void *data; /* A pointer to the first element of the array */ PyObject *descr; /* NULL or data-description (same as descr key of __array_interface__) -- must set ARR_HAS_DESCR flag or this will be ignored. */ } PyArrayInterface;
The flags member may consist of 5 bits showing how the data should be interpreted and one bit showing how the Interface should be interpreted. The data-bits are NPY_ARRAY_C_CONTIGUOUS (0x1), NPY_ARRAY_F_CONTIGUOUS (0x2), NPY_ARRAY_ALIGNED (0x100), NPY_ARRAY_NOTSWAPPED (0x200), and NPY_ARRAY_WRITEABLE (0x400). A final flag NPY_ARR_HAS_DESCR (0x800) indicates whether or not this structure has the arrdescr field. The field should not be accessed unless this flag is present.
Type description examples
For clarity it is useful to provide some examples of the type description and corresponding ~object.__array_interface__ 'descr' entries. Thanks to Scott Gilbert for these examples:
In every case, the 'descr' key is optional, but of course provides more information which may be important for various applications
* Float data typestr == '>f4' descr == [('','>f4')] * Complex double typestr == '>c8' descr == [('real','>f4'), ('imag','>f4')] * RGB Pixel data typestr == '|V3' descr == [('r','|u1'), ('g','|u1'), ('b','|u1')] * Mixed endian (weird but could happen). typestr == '|V8' (or '>u8') descr == [('big','>i4'), ('little','<i4')] * Nested structure struct { int ival; struct { unsigned short sval; unsigned char bval; unsigned char cval; } sub; } typestr == '|V8' (or '<u8' if you want) descr == [('ival','<i4'), ('sub', [('sval','<u2'), ('bval','|u1'), ('cval','|u1') ]) ] * Nested array struct { int ival; double data[16*4]; } typestr == '|V516' descr == [('ival','>i4'), ('data','>f8',(16,4))] * Padded structure struct { int ival; double dval; } typestr == '|V16' descr == [('ival','>i4'),('','|V4'),('dval','>f8')]
It should be clear that any structured type could be described using this interface.
Differences with array interface (version 2)
The version 2 interface was very similar. The differences were largely aesthetic. In particular:
The PyArrayInterface structure had no descr member at the end (and therefore no flag ARR_HAS_DESCR)
The
contextmember of thePyCapsule(formally thedescmember of thePyCObject) returned from__array_struct__was not specified. Usually, it was the object exposing the array (so that a reference to it could be kept and destroyed when the C-object was destroyed). It is now an explicit requirement that this field be used in some way to hold a reference to the owning object.The tuple returned from
__array_interface__['data']used to be a hex-string (now it is an integer or a long integer).There was no
__array_interface__attribute instead all of the keys (except for version) in the__array_interface__dictionary were their own attribute: Thus to obtain the Python-side information you had to access separately the attributes:__array_data____array_shape____array_strides____array_typestr____array_descr____array_offset____array_mask__