[Numpy-discussion] subclassing ndaray

Colin J. Williams cjw at sympatico.ca
Tue Feb 28 17:01:13 CST 2006

Travis Oliphant wrote:

>> Travis Oliphant wrote:
>>> Stefan van der Walt wrote:
>>>>> The __init__ and __new__ methods are not called because they may 
>>>>> have arbitrary signatures.  Instead,  the __array_finalize__ 
>>>>> method is always called.  So, you should use that instead of 
>>>>> __init__.
>>> This is now true in SVN.  Previously, __array_finalize__ was not 
>>> called if the "parent" was NULL.  However, now, it is still called 
>>> with None as the value of the first argument.
>>> Thus __array_finalize__ will be called whenever 
>>> ndarray.__new__(<some subclass>,...) is called.
>> Why this change in style from the the common Python idom of __new__, 
>> __init__, with the same signature to __new__, __array_finalize__ with 
>> possibly different signatures?
> I don't see it as a change in style but adding a capability to the 
> ndarray subclass.   The problem is that arrays can be created in many 
> ways (slicing, ufuncs, etc).   Not all of these ways should go through 
> the __new__/__init__ -- style creation mechanism.   Try inheriting 
> from a float builtin and add attributes.  Then add your float to an 
> instance of your new class and see what happens.

Yes, I've tried this with ndarray - it didn't work.

Later, I realized that it wasn't a good thing to try.

Colin W.

> You will get a float-type on the output.   This is the essence of 
> Paul's insight that sub-classing is rarely useful because you end up 
> having to re-define all the operators anyway to return the value that 
> you want.  He knows whereof he speaks as well, because he wrote MA and 
> UserArray and had experience with Python sub-classing.
> I wanted a mechanism to make it easier to sub-class arrays and have 
> the operators return your object if possible (including all of it's 
> attributes).
> Thus,
> __array_priority__  (a floating point attribute)
> __array_finalize__  (a method called on internal construction of the 
> array wrapper).
> were invented (along with __array_wrap__  which any class can define 
> to have their objects survive ufuncs).
> It was easy enough to see where to call __array_finalize__ in the 
> C-code if somewhat difficult to explain (and get exception handling to 
> work because of my initial over-thinking).
> The signature is just
> __array_finalize__(self, parent):
>    return
> i.e. any return value is ignored (but exceptions are caught).
> I've used the feature succesfully on at least 3-subclasses (chararray, 
> memmap, and matrix) and so I'm actually pretty happy with it.
> __new__ and __init__ are still relevant for constructing your 
> brand-new object.  The __array_finalize__ function is just what the 
> internal contructor that acutally allocates memory will always call to 
> let you set final attributes *every* time your sub-class gets created.
> -Travis

More information about the Numpy-discussion mailing list