[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