Reputation: 4706
Let's look at some very simple behaviour of numpy arrays:
import numpy as np
arr = np.array([1,2,3,4,5])
max_value = arr.max() # returns 5
Now I create a class which inherits from np.ndarray
:
class CustomArray(np.ndarray):
def __new__(cls, *args, **kwargs):
obj = np.array(*args, **kwargs).view(cls)
return obj
new_arr = CustomArray([1,2,3,4,5])
I haven't actually changed any behaviour - I just made a nominal change in what class the object is.
And yet:
new_max_value = new_arr.max() # returns CustomArray(5)
The return value is an CustomArray
instance? Why? arr.max()
didn't return a np.ndarray
instance, just a plain numpy integer.
Similarly, why do both arr == new_arr
and new_arr == arr
return CustomArray
instances? Shouldn't the former call arr.__eq__(new_arr)
, which should return a np.ndarray
instance?
EDIT:
Note that I override the __new__
method for the sake of easy constructors. E.g. the equivalent of np.array([1,2,3,4,5])
can just be CustomArray([1,2,3,4,5])
, whereas if I plainly inherit from np.ndarray
I'd have to do something like new_arr = CustomArray((5,))
; new_arr[:] = np.array([1,2,3,4,5])
.
Upvotes: 5
Views: 724
Reputation: 46
Following the numpy docs: array_wrap gets called at the end of numpy ufuncs and other numpy functions, to allow a subclass to set the type of the return value and update attributes and metadata.
class CustomArray(np.ndarray):
def __new__(cls, a, dtype=None, order=None):
obj = np.asarray(a, dtype, order).view(cls)
return obj
def __array_wrap__(self, out_arr, context=None):
return np.ndarray.__array_wrap__(self, out_arr, context)
c = CustomArray([1,2,3,4])
c.max() # returns 4
Upvotes: 3