[Numpy-discussion] Simplest ndarray subclass __new__ possible?

Travis Oliphant oliphant.travis at ieee.org
Mon Feb 27 22:33:00 CST 2006


Zachary Pincus wrote:

> Hi again.
>
> I would like to put together a wiki page about writing ndarray  
> subclasses because this is obviously a difficult topic, and the  
> available documentation (e.g. looking at defmatrix) doesn't cover all  
> -- or even the most common -- uses.


Great.  Let me see if I can help out with some concepts.

First of all, you should probably mention that UserArray might be what 
people want.   UserArray is a standard "container" class meaning that 
the array is just one of it's attributes and UserArray doesn't inherit 
from the array.    I finally realized that evey though you can 
"directly" inherit from the ndarray, sometimes that is not what you want 
to do, but instead want a capable container class.  I think multiple 
inheritence with other builtins is a big reason to want this feature as 
was pointed out on the list a few days ago.

The biggest reason to inherit from the ndarray, is if you want your 
object to satisify the

isinstance(obj, ndarray) test...

Inheriting from the ndarray is as simple as

class myarray(numpy.ndarray):
          pass


Now, your array will be constructed.  To get your arrays you can either 
use the standard array constructor

array([1,2,3,4]).view(myarray)

Or

use the new myarray constructor --- which now has the same signature as 
ndarray.__new__.

For several reasons (probably not any good ones, though :-) ), the 
default ndarray signature is built for "wrapping" around memory (exposed 
by another object through the buffer protocol in Python) or for creating 
uninitalized new memory.

So, if you over-write the __new__ constructor for your class and want to 
call the ndarray.__new__ constructor you have to realize that you need 
to think of what you are doing in terms of "wrapping" some other created 
piece of memory or "initializing your memory".

If you want your array to be-able to "convert" arbitrary objects to 
arrays, instead, then your constructor could in-fact be as simple as

class myarray(numpy.ndarray):
          def __new__(cls, obj):
                return numpy.array(obj).view(cls)

Then, if you want, you can define an __init__ method to handle setting 
of attributes --- however, if you set some attributes, then you need to 
think about what you want to happen when your new array gets "sliced" or 
added to.  Because the internal code will create your new array (without 
calling new) and then call

__array_finalize__(self, parent)

where parent could be None (if there is no parent --- i.e. this is a new 
array).

Any attributes you define should also be defined here so they get passed 
on to all arrays that are created..


I hope this helps some.


-Travis






More information about the Numpy-discussion mailing list