[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