User guide
NumPy User Guide, Release 1.9.0
1. If needed create a new C-structure to handle each instance of your type. A typical C-structure would be:
typedef _new_struct {
PyArrayObject base;
/
*
new things here
*
/
} NewArrayObject;
Notice that the full PyArrayObject is used as the first entry in order to ensure that the binary layout of instances
of the new type is identical to the PyArrayObject.
2. Fill in a new Python type-object structure with pointers to new functions that will over-ride the default behavior
while leaving any function that should remain the same unfilled (or NULL). The tp_name element should be
different.
3. Fill in the tp_base member of the new type-object structure with a pointer to the (main) parent type object. For
multiple-inheritance, also fill in the tp_bases member with a tuple containing all of the parent objects in the
order they should be used to define inheritance. Remember, all parent-types must have the same C-structure for
multiple inheritance to work properly.
4. Call PyType_Ready (<pointer_to_new_type>). If this function returns a negative number, a failure occurred
and the type is not initialized. Otherwise, the type is ready to be used. It is generally important to place a
reference to the new type into the module dictionary so it can be accessed from Python.
More information on creating sub-types in C can be learned by reading PEP 253 (available at
http://www.python.org/dev/peps/pep-0253).
Specific features of ndarray sub-typing
Some special methods and attributes are used by arrays in order to facilitate the interoperation of sub-types with the
base ndarray type.
The __array_finalize__ method
ndarray.__array_finalize__
Several array-creation functions of the ndarray allow specification of a particular sub-type to be created. This
allows sub-types to be handled seamlessly in many routines. When a sub-type is created in such a fashion,
however, neither the __new__ method nor the __init__ method gets called. Instead, the sub-type is allocated
and the appropriate instance-structure members are filled in. Finally, the __array_finalize__ attribute
is looked-up in the object dictionary. If it is present and not None, then it can be either a CObject containing
a pointer to a PyArray_FinalizeFunc or it can be a method taking a single argument (which could be
None).
If the __array_finalize__ attribute is a CObject, then the pointer must be a pointer to a function with the
signature:
(int) (PyArrayObject
*
, PyObject
*
)
The first argument is the newly created sub-type. The second argument (if not NULL) is the “parent” array (if
the array was created using slicing or some other operation where a clearly-distinguishable parent is present).
This routine can do anything it wants to. It should return a -1 on error and 0 otherwise.
If the __array_finalize__ attribute is not None nor a CObject, then it must be a Python method that takes
the parent array as an argument (which could be None if there is no parent), and returns nothing. Errors in this
method will be caught and handled.
The __array_priority__ attribute
ndarray.__array_priority__
This attribute allows simple but flexible determination of which sub- type should be considered “primary” when
104 Chapter 5. Using Numpy C-API