[Numpy-discussion] Multiple inheritance from ndarray
Robert Lupton
rhl at astro.princeton.edu
Tue Mar 21 08:45:29 CST 2006
I've finally found time to return to this problem. Travis's made the
suggestion that I could use code along the lines of:
> class Image(ndarray, actImage):
> def __new__(subtype, *args)
> act1 = actImage.__new__(actImage, *args)
> actImage.__init__(act1, *args)
> arr = array(act1.getArray(), 'd', copy=False)
> self = arr.view(subtype)
>
> return self
and this makes sense. Unfortunately, the arr.view(subtype) fails:
TypeError: Cannot change descriptor for objectarray.
[incidently, is that a typo for "object array"; the string's built
by "C string" "concatenation").
Ideas?
The C type "actImage" looks like:
typedef struct actImage {
int nrow; // number of rows
int ncol; // number of columns
void *base; // allocated memory, if owned by this object
int baseRefCount; // reference counter for base
double **rows; // Fluxes for pixels
PyArrayObject *_array; // pointer to Numeric array; used by
actNumPy
} actImage;
The _array is set in the C actImage constructor with:
im->_array = (PyArrayObject *)PyArray_FromDimsAndData(2, dims,
PyArray_DOUBLE, (void *)im->base);
and getArray is a wrapper around:
PyObject *actImageGetNumPy(const actImage *im)
{
Py_XINCREF(im->_array);
return PyArray_Return(im->_array);
}
R
> Robert Lupton wrote:
>> I have a swig extension that defines a class that inherits from
>> both a personal C-coded image struct (actImage), and also from
>> Numeric's UserArray. This works very nicely, but I thought that
>> it was about time to upgrade to numpy.
>>
>> The code looks like:
>>
>> from UserArray import *
>>
>> class Image(UserArray, actImage):
>> def __init__(self, *args):
>> actImage.__init__(self, *args)
>> UserArray.__init__(self, self.getArray(), 'd',
>> copy=False, savespace=False)
>>
>> I can't figure out how to convert this to use ndarray, as ndarray
>> doesn't
>> seem to have an __init__ method, merely a __new__.
>>
>
>
> Yes, the ndarray method doesn't have an __init__ method (so you
> don't have to call it).
>
> What you need to do is write a __new__ method for your class.
> However, with multiple-inheritance the details matter. You may
> actually want to have your C-coded actImage class inherit (in C)
> from the ndarray. If you would like help on that approach let me
> know (I'll need to understand your actImage a bit better).
> But, this can all be done in Python, too, but it is a bit of effort
> to make sure things get created correctly. Perhaps it might make
> sense to actually include a slightly modified form of the UserArray
> in NumPy as a standard "container-class" (instead of a sub-class)
> of the ndarray. In reality, a container class like UserArray and
> a sub-class are different things.
>
> Here's an outline of what you need to do. This is, of course,
> untested.... For example, I don't really know what actImage is.
>
> from numpy import ndarray, array
>
> class Image(ndarray, actImage):
> def __new__(subtype, *args)
> act1 = actImage.__new__(actImage, *args)
> actImage.__init__(act1, *args)
> arr = array(act1.getArray(), 'd', copy=False)
> self = arr.view(subtype)
> # you might need to copy attributes from act1 over to self
> here...
> return self
>
>
> The problem here, is that apparently you are creating the array
> first in actImage.__init__ and then passing it to UserArray. The
> ndarray constructor wants to either create the array itself or use
> a buffer-exposing object to use as the memory.
> Keep us posted as your example is a good one that can help us all
> learn.
>
> -Travis
>
>
>
>
>
More information about the Numpy-discussion
mailing list