From: Sebastian H. <ha...@ms...> - 2006-07-23 03:39:27
|
Hi, I have a (medical) image file. I wrote a nice interface based on memmap using numarray. The class design I used was essentially to return a numarray array object with a new "custom" attribute giving access to special information about the base file. Now with numpy I noticed that a numpy object does not allow adding new attributes !! (How is this ? Why ?) Travis already suggested (replying to one of my last postings) to create a new sub class of numpy.ndarray. But how do I initialize an object of my new class to be "basically identically to" an existing ndarray object ? Normally I could do class B(N.ndarray): pass a=N.arange(10) a.__class__ = B BUT I get this error: #>>> a.__class__ = B Traceback (most recent call last): File "<input>", line 1, in ? TypeError: __class__ assignment: only for heap types What is a "heap type" ? Why ? How can I do what I want ? Thanks, Sebastian Haase |
From: Eric F. <ef...@ha...> - 2006-07-23 07:12:15
|
Sebastian Haase wrote: > Hi, > I have a (medical) image file. > I wrote a nice interface based on memmap using numarray. > The class design I used was essentially to return a numarray array > object with a new "custom" attribute giving access to special > information about the base file. > > Now with numpy I noticed that a numpy object does not allow adding new > attributes !! (How is this ? Why ?) > > Travis already suggested (replying to one of my last postings) to create > a new sub class of numpy.ndarray. > > But how do I initialize an object of my new class to be "basically > identically to" an existing ndarray object ? > Normally I could do > class B(N.ndarray): > pass > a=N.arange(10) > a.__class__ = B Isn't this what you need to do instead? In [1]:import numpy as N In [2]:class B(N.ndarray): ...: pass ...: In [3]:a = B(N.arange(10)) In [4]:a.__class__ Out[4]:<class '__main__.B'> In [5]:a.stuff = 'stuff' I don't think it makes sense to try to change the __class__ attribute by assignment. Eric |
From: Filip W. <fil...@gm...> - 2006-07-23 20:04:39
|
On 7/23/06, Eric Firing <ef...@ha...> wrote: > Sebastian Haase wrote: > > Hi, > > I have a (medical) image file. > > I wrote a nice interface based on memmap using numarray. > > The class design I used was essentially to return a numarray array > > object with a new "custom" attribute giving access to special > > information about the base file. > > > > Now with numpy I noticed that a numpy object does not allow adding new > > attributes !! (How is this ? Why ?) > > > > Travis already suggested (replying to one of my last postings) to create > > a new sub class of numpy.ndarray. > > > > But how do I initialize an object of my new class to be "basically > > identically to" an existing ndarray object ? > > Normally I could do > > class B(N.ndarray): > > pass > > a=N.arange(10) > > a.__class__ = B > > Isn't this what you need to do instead? > > In [1]:import numpy as N > > In [2]:class B(N.ndarray): > ...: pass > ...: > > In [3]:a = B(N.arange(10)) It won't work like that. The constructor for the ndarray is: | ndarray.__new__(subtype, shape=, dtype=int_, buffer=None, | offset=0, strides=None, fortran=False) so you will get either an exception caused by inappropriate shape value or completely wrong result. >>> numpy.ndarray([1,2]) array([[10966528, 18946344]]) >>> numpy.ndarray([1,2]).shape (1, 2) >>> numpy.ndarray(numpy.arange(5)) array([], shape=(0, 1, 2, 3, 4), dtype=int32) And this is a thing you souldn't do rather than a bug. To create an instance of ndarray's subclass B from ndarray object, one need to call the ndarray.view method or the ndarray.__new__ constructor explicitly: class B(numpy.ndarray): def __new__(subtype, data): if isinstance(data, B): return data if isinstance(data, numpy.ndarray): return data.view(subtype) arr = numpy.array(data) return numpy.ndarray.__new__(B, shape=arr.shape, dtype=arr.dtype, buffer=arr) A good example of subclasing ndarray is the matrix class in core/defmatrix.py (SVN version). cheers, fw |
From: Kevin J. <ja...@bi...> - 2006-07-23 17:02:12
|
On 7/22/06, Sebastian Haase <ha...@ms...> wrote: > > Normally I could do > class B(N.ndarray): > pass > a=N.arange(10) > a.__class__ = B > > BUT I get this error: > #>>> a.__class__ = B > Traceback (most recent call last): > File "<input>", line 1, in ? > TypeError: __class__ assignment: only for heap types > > What is a "heap type" ? Why ? How can I do what I want ? Assigning to __class__ makes sense for objects that allocate a dictionary for storage of attributes or have slots allocated to hold the values. The heap type error is due to a missing flag in the class definition and could be corrected. However, it may not be the best thing to do. Calling B(array) is certainly safer, although a bit more expensive. -Kevin |
From: Sebastian H. <ha...@ms...> - 2006-07-23 19:19:18
|
Kevin Jacobs <ja...@bi...> wrote: > On 7/22/06, *Sebastian Haase* <ha...@ms... > <mailto:ha...@ms...>> wrote: > > Normally I could do > class B(N.ndarray): > pass > a=N.arange(10) > a.__class__ = B > > BUT I get this error: > #>>> a.__class__ = B > Traceback (most recent call last): > File "<input>", line 1, in ? > TypeError: __class__ assignment: only for heap types > > What is a "heap type" ? Why ? How can I do what I want ? > > > > Assigning to __class__ makes sense for objects that allocate a > dictionary for storage of attributes or have slots allocated to hold the > values. The heap type error is due to a missing flag in the class > definition and could be corrected. However, it may not be the best > thing to do. Calling B(array) is certainly safer, although a bit more > expensive. > > -Kevin > Thanks for the replies. Googling for this I was surprised myself that it IS legal (and done) to assign to obj.__class__. Kevin, I tried what you suggested first -- I think in C++ it would be called "using the copy-constructor". But I get an error - something like: "__new__() needs at least 3 arguments" In other words: (maybe?) in Python there is not always a "copy-constructor" (in fact there is no constructor overloading at all ...) So if there is "just a missing flag" - it would be great if this could be put in. It turns out that the "assigning to __class__"-scheme worked for the ndarray subclass "memmap" (i.e. I was sub classing from memmap and then I could assing origMemmapObj.__class__ = myClass) Thanks, Sebastian Haase |
From: Sebastian H. <ha...@ms...> - 2006-07-24 20:28:15
|
On Monday 24 July 2006 12:23, Travis Oliphant wrote: > Sebastian Haase wrote: > > Hi, > > I have a (medical) image file. > > I wrote a nice interface based on memmap using numarray. > > The class design I used was essentially to return a numarray array > > object with a new "custom" attribute giving access to special > > information about the base file. > > > > Now with numpy I noticed that a numpy object does not allow adding new > > attributes !! (How is this ? Why ?) > > > > Travis already suggested (replying to one of my last postings) to create > > a new sub class of numpy.ndarray. > > > > But how do I initialize an object of my new class to be "basically > > identically to" an existing ndarray object ? > > Normally I could do > > class B(N.ndarray): > > pass > > a=N.arange(10) > > a.__class__ = B > > > > BUT I get this error: > > #>>> a.__class__ = B > > Traceback (most recent call last): > > File "<input>", line 1, in ? > > TypeError: __class__ assignment: only for heap types > > > > What is a "heap type" ? Why ? How can I do what I want ? > > A heap type is one created in Python (i.e. not builtin with C). > > You should be able to do > > a = a.view(B) > > -Travis Thanks - (I'm just replying because I assume your helpful answer was mistakenly sent to me only and did not make it to the list) |