[Numpy-discussion] subclassing ndaray
Colin J. Williams
cjw at sympatico.ca
Sat Feb 25 05:18:07 EST 2006
Travis Oliphant wrote:
> Colin J. Williams wrote:
>
>> I have a subclass Bar, a 1-dim array which has some methods and some
>> attributes. One of the attributes is a view of the Bar to permit
>> different shaping.
>
>
> The ndarray handles sub-classing a little-bit differently. All array
> constructors go through the same C-code call which can create
> sub-classes as well. (it's what gets called by ndarray.__new__).
>
> If there is a parent object, then additionally, the
>
> __array_finalize__(self, parent)
>
> method is called right-after creation of the sub-class. This is
> where attributes should be finalized. But, care must be taken in this
> code so that a recursion is not setup
>
> If this mechanism is not sufficient for you, then you need to use a
> container class (for this reason UserArray has been resurrected to
> serve as a default container class model---it needs more testing,
> however).
> The problem __array_finalize__ helps fix is how to get subclasses to
> work well without having to re-define every single special method like
> UserArray does.
>
> For the most part it seems to work, but I suppose it creates a few
> surprises if you are not aware of what is going on.
>
> The most important thing to remember is that attributes are not
> automatically carried over to new instances because new instances can
> be created without every calling __new__ or __init__.
>
> I'm sure this mechanism can be improved upon and I welcome suggestions.
Thanks for this.
Does this mean that whenever we subclass ndarray, we should use
__array_finalize__ (with its additional 'parent' parameter) instead of
Python's usual __init__?
It would help if you could clarify the role of 'parent'.
[Dbg]>>> h(self.__array_finalize__)
Help on built-in function __array_finalize__:
__array_finalize__(...)
Is parent the next type up in the type hierarchy? If so, can this not
be determined from self.__class__?
I've tried a similar operation with the Python library's sets.Set.
There, __init__ is called, ensuring that the expression is of the
appropriate sub-type.
>
>> Suppose that 'a' is an instance of 'Bar', which has a method 'show'
>> and a view attribute 'v'.
>> a ^ 15 returns a Bar instance, with its methods but without the
>> attributes.
>>
>> I am attempt to change this, Bar has a method __xor__, see below:
>>
>> def __xor__(self, other):
>> ''' Exclusive or: __xor__(x, y) => x ^ y . '''
>> z=
>>
>> 1
>> << this loops to the recursion limit
>> result= ArrayType.__xor__(self, other)
>> n= self.n
>> result.n= n
>> result.rowSize= self.rowSize
>> result.show= self.show
>> result.v= _n.reshape(result.view(), (n*n, n*n))
>> return result
>
>
>
> Look at the __array_finalize__ method in defmatrix.py for ideas about
> how it can be used.
def __array_finalize__(self, obj):
ndim = self.ndim
if ndim == 0:
self.shape = (1,1)
elif ndim == 1:
self.shape = (1,self.shape[0])
return
These are functions for which one would use __init__ in numarray. This
doesn't describe or illustrate the role or purpose of the parent object.
Colin W.
More information about the NumPy-Discussion
mailing list