[Numpy-discussion] Simplest ndarray subclass __new__ possible?
Travis Oliphant
oliphant.travis at ieee.org
Mon Feb 27 22:33:00 EST 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