I have an array subclass, where some of the extra attributes are only valid for the object's original shape. Is there a way to make sure that all array shape changing operations return a normal numpy array instead of an instance of my class?
I've already written array_wrap, but this doesn't seem to have any effect on operations like np.mean
, np.sum
or np.rollaxis
. These all just return an instance of my class.
import numpy as np
class NewArrayClass(np.ndarray):
__array_priority__ = 3.0
def __array_wrap__(self, out_arr, context=None):
if out_arr.shape == self.shape:
out = out_arr.view(new_array)
# Do a bunch of class dependant initialization and attribute copying.
# ...
return out
else:
return np.asarray(out_arr)
A = np.arange(10)
A.shape = (5, 2)
A = arr.view(NewArrayClass)
# Would like this to be np.ndarray, but get new_array_class.
print type(np.sum(A, 0))
I figure I have to do something in __new__
or __array_finalize__
, but I haven't a clue what.
Update:
After carefully reading the numpy documentation on subclassing (http://docs.scipy.org/doc/numpy/user/basics.subclassing.html), all array shape changing operations are doing the 'new from template' operation. So the question becomes, how do you make the 'new from template' operation return ndarray instances instead of instances of my class. As far as I can tell, __new__
is never called within these functions.
Alternative:
Assuming the above is not possible, how do I at least identify in __array_finalize__
the new from template operation (as opposed to view casting)开发者_JS百科? This would at least let me dereference some attributes that are copied by reference. I could also set a flag or something telling the new instance that its shape is invalid.
If you are not introducing any new members to your NewArrayClass
instances, you can reassign the __class__
attribute of the returned instances.
A.__class__ = np.ndarray
The point is why would you like to do such a thing. Do you engage in strict type checking elsewhere? You'd go far more with duck typing.
精彩评论