I have a class that is a subclass of numpy.ndarray
. Following this example I have a class Test
that behaves like numpy.ndarray
but has an additional attribute description
:
>>> f = Test([0., 1., 2.], description="f")
>>> f
array([0., 1., 2.])
>>> f.description
'f'
f
behaves just like numpy.ndarray
and the results of all mathematical operations will also have the description
attribute.
>>> fplusone = f + 1.
>>> fplusone
array([1., 2., 3.])
>>> fplusone.description
'f'
In a more complex case it has the following behavior:
>>> g = Test([1., 3., 2], description="g")
>>> g
array([1., 3., 2.])
>>> g.description
'g'
>>> fplusg = f + g
>>> fplusg
array([1., 4., 4.])
>>> fplusg.description
'f'
>>> gplusf= g + f
>>> gplusf
array([1., 4., 4.])
>>> gplusf.description
'g'
Note: The order matters for the outcome of the description
attribute.
That's a behavior I do not want. Basically I would like to have that the result of any math operation is a numpy.ndarray
and not an instance of Test
.
One idea is to overload all operators, e.g.:
>>> class Test2(Test):
>>>
>>> def __add__(self, val):
>>> return numpy.array(super().__add__(val))
>>> f2 = Test2([0., 1., 2.], description="f2")
>>> f2.description
'f2'
>>> (f2 + 1.).description
AttributeError: 'numpy.ndarray' object has no attribute 'description'
I would like to have this behavior for all Numpy ufuncs, too, e.g. this should also raise an AttributeError
:
>>> fgmax = numpy.maximum(f, g)
>>> fgmax
array([1., 3., 2.])
>>> fgmax.description
'f'
So my questions are:
Is there an easy way of doing this without overloading every single arithmetic operator by hand? And how can this be achieved for every possible Numpy universal function?
I'm also having an eye on the overhead that is caused by invoking the additional numpy.array()
.
Something like this would invoke numpy.array()
four times if implemented for all operators as shown above:
>>> f * g + f**2 / g
But all that matters for me is that the end result is a numpy.ndarray
, e.g.:
>>> numpy.array(f * g + f**2 / g)