Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making an numpy array subclass where all shape changing operations return a normal array

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)? 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.

like image 251
kiyo Avatar asked Mar 29 '11 15:03

kiyo


1 Answers

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.

like image 158
janislaw Avatar answered Oct 05 '22 08:10

janislaw