[Pyrex] Subclassing numpy.ndarray with Pyrex

Pierre GM pgmdevlist at gmail.com
Tue Feb 6 04:11:22 UTC 2007


On Monday 05 February 2007 19:56:12 you wrote:
> Pierre GM wrote:
> > Moreover, the __array_finalize__ seems to be called
> > before the __new__ of my subclass, which is a tad surprising
>
> Pyrex generates a call to the base class tp_new method
> before calling your __new__ method, so if the base class
> calls __array_finalize__ during its initialisation, then
> it will get called before your __new__ method. 

Mmh. Now I'm not that surprised, actually. According to the official doc, 
__array_finalize__ is called when present (I pasted the corresponding 
paragraph at the end of the message. As I don't fully understand all its 
implications, I prefer not to leave out some potentially important 
information out). 
In pure Python, it's rather easy to overload the __new__ method of a ndarray 
subclass, and have it return a view of the ndarray, which calls 
__array_finalize__ and permits to finalize the object. The "obj" argument is 
then what was returned by the caller (either __new__ or any other method that 
doesn't recreate an array from scratch).

OK, so that answers one question, why __array_finalize__ got called before 
__new__. Which implies that I probably won't be able to use it at all for my 
own purpose, at it's gonna conflict w/ numpy. Darn. And I can't overload 
__new__ either, as ndarray.__new__ doesn't take optional arguments. 'm 'fraid 
all the initialization will have to take place outside (in the subarray 
constructor).

Playing a bit more with the example I gave in a previous email, the segfault 
seems  to occur during the calculation of (x+1). Overloading add in Pyrex:
#...
    def __add__(self, other):
        print "__add__"
        result = _N.ndarray.__add__(self, other)
        print "__added__, and got %s as %s from %s" % (result, type(result), 
type(self))
        result._info = self._info
        print "and I updated _info..."
        return result
#...
and using it with
>>>print (x+1)
in python shows that I never get to the ` result._info = self._info` part. 
What happens there ?

I'm sorry, I know it's a lot of questions for a single thread, but I'm tryng 
hard to understand what happens (and to postpone my introduction to C...)

Thanks again for your time.

#

__array_finalize__ doc
"Several array-creation functions of the ndarray allow specification of a 
particular sub-type to be created. This allows sub-types to be handled 
seamlessly in many routines. When a sub-type is created in such a fashion, 
however, neither the new method nor the init methods gets called. Instead, 
the sub-type is allocated and the appropriate instance-structure members are 
filled in. Finally, the array finalize attribute is looked-up in the object 
dictionary. If it is present and not None, then it can be either a CObject 
containing a pointer to a PyArray FinalizeFunc or it can be a method taking a 
single argument (which could be None). 
If the __array_finalize__  attribute is a CObject, then the pointer must be a 
pointer to a function with the signature:
   (int) (PyArrayObject *, PyObject *)
The first argument is the newly created sub-type. The second argument (if not
NULL) is the “parent” array (if the array was created using slicing or some 
other operation where a clearly-distinguishable parent is present). This 
routine can do anything it wants to. It should return a -1 on error and 0 
otherwise. 
   If the array finalize attribute is not None nor a CObject, then it must be
a method that takes the parent array as an argument (which could be None if 
there is no parent), and returns nothing. Errors in this method will be 
caught.
"




More information about the Pyrex mailing list