User guide

NumPy User Guide, Release 1.9.0
MySubClass([1, 3, 5, 7, 9])
>>> ret.info
’spam’
Note that the ufunc (np.add) has called the __array_wrap__ method of the input with the high-
est __array_priority__ value, in this case MySubClass.__array_wrap__, with arguments self
as obj, and out_arr as the (ndarray) result of the addition. In turn, the default __array_wrap__
(ndarray.__array_wrap__) has cast the result to class MySubClass, and called __array_finalize__ -
hence the copying of the info attribute. This has all happened at the C level.
But, we could do anything we wanted:
class SillySubClass(np.ndarray):
def __array_wrap__(self, arr, context=None):
return ’I lost your data’
>>> arr1 = np.arange(5)
>>> obj = arr1.view(SillySubClass)
>>> arr2 = np.arange(5)
>>> ret = np.multiply(obj, arr2)
>>> ret
’I lost your data’
So, by defining a specific __array_wrap__ method for our subclass, we can tweak the output from ufuncs. The
__array_wrap__ method requires self, then an argument - which is the result of the ufunc - and an optional
parameter context. This parameter is returned by some ufuncs as a 3-element tuple: (name of the ufunc, argument
of the ufunc, domain of the ufunc). __array_wrap__ should return an instance of its containing class. See the
masked array subclass for an implementation.
In addition to __array_wrap__, which is called on the way out of the ufunc, there is also an
__array_prepare__ method which is called on the way into the ufunc, after the output arrays are created but
before any computation has been performed. The default implementation does nothing but pass through the array.
__array_prepare__ should not attempt to access the array data or resize the array, it is intended for setting the
output array type, updating attributes and metadata, and performing any checks based on the input that may be desired
before computation begins. Like __array_wrap__, __array_prepare__ must return an ndarray or subclass
thereof or raise an error.
2.8.10 Extra gotchas - custom __del__ methods and ndarray.base
One of the problems that ndarray solves is keeping track of memory ownership of ndarrays and their views. Consider
the case where we have created an ndarray, arr and have taken a slice with v = arr[1:]. The two objects are
looking at the same memory. Numpy keeps track of where the data came from for a particular array or view, with the
base attribute:
>>> # A normal ndarray, that owns its own data
>>> arr = np.zeros((4,))
>>> # In this case, base is None
>>> arr.base is None
True
>>> # We take a view
>>> v1 = arr[1:]
>>> # base now points to the array that it derived from
>>> v1.base is arr
True
>>> # Take a view of a view
>>> v2 = v1[1:]
42 Chapter 2. Numpy basics