my derived ndarray class object loses its attribute after a transpose()
Hi, this question might habe been answered before: I have my own ndarray-derived class. I did this, so that I can add another "custom attribute" -- let's say arr.filename All works very except, except when I do arr2 = arr.transpose() my arr2 is still of the *type* of my derived class, however trying a arr2.filename now gives me an AtttributeError. What am I doing wrong? How can this be fixed? (I'm using numpy 1.0.1 - please let me know if this has been fixed since) Thanks, Sebastian Haase
On Friday 23 November 2007 03:25:37 Sebastian Haase wrote:
Hi, this question might habe been answered before: I have my own ndarray-derived class. I did this, so that I can add another "custom attribute" -- let's say arr.filename
Sebastian, Could you post the __new__ and __array_finalize__ for your class ? Are you sure you update the attribute in __array_finalize__ ? And this page may come handy: http://www.scipy.org/Subclasses
On Nov 23, 2007 3:37 PM, Pierre GM <pgmdevlist@gmail.com> wrote:
On Friday 23 November 2007 03:25:37 Sebastian Haase wrote:
Hi, this question might habe been answered before: I have my own ndarray-derived class. I did this, so that I can add another "custom attribute" -- let's say arr.filename
Sebastian, Could you post the __new__ and __array_finalize__ for your class ? Are you sure you update the attribute in __array_finalize__ ? And this page may come handy: http://www.scipy.org/Subclasses
Aah - I guess I did not do my homework ;-) Here is my code: class ndarray_inMrcFile(N.memmap): pass data = self.data data.__class__ = ndarray_inMrcFile Two points: 1.) Please don't get distracted by the way how I change the class type "after the fact". I get the data as a memmaped slice from a file. Then I do some (potentially not entirely clean) acrobatic to have this slice change it's class-type so that I can attach the original memmap (+ other attributes, such as filename) onto the ndarray 2.) I guess the """class ndarray_inMrcFile(N.memmap): pass""" construct is to simplistic .... Could someone suggest a *minimal* definition, so that my attributes would be preserved ? A few comments about the wiki page: 1) The example does not show the printed info, such as "__new__ received %s", in the example session 2) I don't understand, why in the example the "info" attribute is set in "__new__()", even though the text above says: """However, we need to keep in mind that any attribute that we define in the __new__ method will be shared among all the instances. If we want instance-specific attributes, we still need some specific initialization. We cannot use the __init__ method, as it won't be called. That's where __array_finalize__ comes to play.""" 3) the text about "The __array_finalize__ method" should at least once say that it is defined as "def __array_finalize__(self,obj)" -- otherwise I could only guess where the "obj" comes from. 4) related to the text after: "In other terms, __array_finalize__ is called" How do I know if a function or method actually invokes __new__ ;-) ? Would I have to study the numpy source ? 5) For the "__array_finalize__ method" there a text that says: """Subclasses inherit a default implementation of this method that does nothing""" --- but how about "__new__()" : what happens if you don't define that (either) ? (Hope these comments are helpful) Thanks for the help, Sebastian
On Nov 23, 2007 4:43 PM, Sebastian Haase <haase@msg.ucsf.edu> wrote:
On Nov 23, 2007 3:37 PM, Pierre GM <pgmdevlist@gmail.com> wrote:
On Friday 23 November 2007 03:25:37 Sebastian Haase wrote:
Hi, this question might habe been answered before: I have my own ndarray-derived class. I did this, so that I can add another "custom attribute" -- let's say arr.filename
Sebastian, Could you post the __new__ and __array_finalize__ for your class ? Are you sure you update the attribute in __array_finalize__ ? And this page may come handy: http://www.scipy.org/Subclasses
Aah - I guess I did not do my homework ;-) Here is my code: class ndarray_inMrcFile(N.memmap): pass
data = self.data data.__class__ = ndarray_inMrcFile
Two points: 1.) Please don't get distracted by the way how I change the class type "after the fact". I get the data as a memmaped slice from a file. Then I do some (potentially not entirely clean) acrobatic to have this slice change it's class-type so that I can attach the original memmap (+ other attributes, such as filename) onto the ndarray
2.) I guess the """class ndarray_inMrcFile(N.memmap): pass""" construct is to simplistic .... Could someone suggest a *minimal* definition, so that my attributes would be preserved ?
A few comments about the wiki page: 1) The example does not show the printed info, such as "__new__ received %s", in the example session
2) I don't understand, why in the example the "info" attribute is set in "__new__()", even though the text above says: """However, we need to keep in mind that any attribute that we define in the __new__ method will be shared among all the instances. If we want instance-specific attributes, we still need some specific initialization. We cannot use the __init__ method, as it won't be called. That's where __array_finalize__ comes to play."""
3) the text about "The __array_finalize__ method" should at least once say that it is defined as "def __array_finalize__(self,obj)" -- otherwise I could only guess where the "obj" comes from.
4) related to the text after: "In other terms, __array_finalize__ is called" How do I know if a function or method actually invokes __new__ ;-) ? Would I have to study the numpy source ?
5) For the "__array_finalize__ method" there a text that says: """Subclasses inherit a default implementation of this method that does nothing""" --- but how about "__new__()" : what happens if you don't define that (either) ?
(Hope these comments are helpful)
Thanks for the help, Sebastian
First try seems to show that just changing my class def to: class ndarray_inMrcFile(N.memmap): def __array_finalize__(self,obj): self.Mrc = getattr(obj, 'Mrc', None) Seems to add the wanted attribute back into result of transpose(). However now I get (many!) exceptions like: Exception exceptions.AttributeError: "'ndarray_inMrcFile' object has no attribut e '_mmap'" in <bound method ndarray_inMrcFile.__del__ of ndarray_inMrcFile([ 6,.... Do I need to call super.__array_finalize__(obj) first ? -Sebastian
First try seems to show that just changing my class def to: class ndarray_inMrcFile(N.memmap): def __array_finalize__(self,obj): self.Mrc = getattr(obj, 'Mrc', None)
Seems to add the wanted attribute back into result of transpose().
Yep. Specific subclass attributes should be defined in __array_finalize__.
However now I get (many!) exceptions like: Exception exceptions.AttributeError: "'ndarray_inMrcFile' object has no attribut e '_mmap'" in <bound method ndarray_inMrcFile.__del__ of ndarray_inMrcFile([ 6,....
Do I need to call super.__array_finalize__(obj) first ?
Nope, you just need a __new__ that calls the __new__ of you parent class. Keep it minimal.
On Nov 23, 2007 5:01 PM, Sebastian Haase <haase@msg.ucsf.edu> wrote:
On Nov 23, 2007 4:43 PM, Sebastian Haase <haase@msg.ucsf.edu> wrote:
On Nov 23, 2007 3:37 PM, Pierre GM <pgmdevlist@gmail.com> wrote:
On Friday 23 November 2007 03:25:37 Sebastian Haase wrote:
Hi, this question might habe been answered before: I have my own ndarray-derived class. I did this, so that I can add another "custom attribute" -- let's say arr.filename
Sebastian, Could you post the __new__ and __array_finalize__ for your class ? Are you sure you update the attribute in __array_finalize__ ? And this page may come handy: http://www.scipy.org/Subclasses
Aah - I guess I did not do my homework ;-) Here is my code: class ndarray_inMrcFile(N.memmap): pass
data = self.data data.__class__ = ndarray_inMrcFile
Two points: 1.) Please don't get distracted by the way how I change the class type "after the fact". I get the data as a memmaped slice from a file. Then I do some (potentially not entirely clean) acrobatic to have this slice change it's class-type so that I can attach the original memmap (+ other attributes, such as filename) onto the ndarray
2.) I guess the """class ndarray_inMrcFile(N.memmap): pass""" construct is to simplistic .... Could someone suggest a *minimal* definition, so that my attributes would be preserved ?
A few comments about the wiki page: 1) The example does not show the printed info, such as "__new__ received %s", in the example session
2) I don't understand, why in the example the "info" attribute is set in "__new__()", even though the text above says: """However, we need to keep in mind that any attribute that we define in the __new__ method will be shared among all the instances. If we want instance-specific attributes, we still need some specific initialization. We cannot use the __init__ method, as it won't be called. That's where __array_finalize__ comes to play."""
3) the text about "The __array_finalize__ method" should at least once say that it is defined as "def __array_finalize__(self,obj)" -- otherwise I could only guess where the "obj" comes from.
4) related to the text after: "In other terms, __array_finalize__ is called" How do I know if a function or method actually invokes __new__ ;-) ? Would I have to study the numpy source ?
5) For the "__array_finalize__ method" there a text that says: """Subclasses inherit a default implementation of this method that does nothing""" --- but how about "__new__()" : what happens if you don't define that (either) ?
(Hope these comments are helpful)
Thanks for the help, Sebastian
First try seems to show that just changing my class def to: class ndarray_inMrcFile(N.memmap): def __array_finalize__(self,obj): self.Mrc = getattr(obj, 'Mrc', None)
Seems to add the wanted attribute back into result of transpose(). However now I get (many!) exceptions like: Exception exceptions.AttributeError: "'ndarray_inMrcFile' object has no attribut e '_mmap'" in <bound method ndarray_inMrcFile.__del__ of ndarray_inMrcFile([ 6,....
Do I need to call super.__array_finalize__(obj) first ?
-Sebastian
This seems to work without any problem now: class ndarray_inMrcFile(N.ndarray): def __array_finalize__(self,obj): self.Mrc = getattr(obj, 'Mrc', None) Comments? -Sebastian
This seems to work without any problem now: class ndarray_inMrcFile(N.ndarray): def __array_finalize__(self,obj): self.Mrc = getattr(obj, 'Mrc', None)
Comments?
That should work if you want a subclass of ndarray. That probably won't if you want a subclass of memmap. Once again, I'd do a def __new__(**options) N.memmap.__new__(**options) or something to this effect...
On Nov 23, 2007 5:18 PM, Pierre GM <pgmdevlist@gmail.com> wrote:
This seems to work without any problem now: class ndarray_inMrcFile(N.ndarray): def __array_finalize__(self,obj): self.Mrc = getattr(obj, 'Mrc', None)
Comments?
That should work if you want a subclass of ndarray. That probably won't if you want a subclass of memmap. Once again, I'd do a def __new__(**options) N.memmap.__new__(**options) or something to this effect...
One more question on this: If I really don't need the memmap features explicitely anymore, and decide to derive from N.ndarray: Is it correct to assume that N.ndarray does *not* do it's own N.ndarray.__new__(**options) or so, that I would have to call ? (In other words: If I derive from N.ndarray I do not need to do a def __new__(**options): N.ndarray.__new__(**options) , right?) -Sebastian
Is it correct to assume that N.ndarray does *not* do it's own N.ndarray.__new__(**options) or so, that I would have to call ? (In other words: If I derive from N.ndarray I do not need to do a def __new__(**options): N.ndarray.__new__(**options) , right?)
That'd work if ndarray.__new__ were accepting an extra dictionary of parameters, a la **options. This is not the case. So, following the example in the wiki, if you want to build an InfoArray with InfoArray(x,info={}), you will need a __new__method to process the argument "info" that ndarray does not recognize. True, you could first create your object, then fill in as needed, such as:
x=InfoArray([1,2,3]) x.info = {'name':'x'}
It looks less clear than
InfoArray([1,2,3], info= {'name':'x'} don't you think ?
2.) I guess the """class ndarray_inMrcFile(N.memmap): pass""" construct is to simplistic .... Could someone suggest a *minimal* definition, so that my attributes would be preserved ?
Mmh, I would at least try to explicitly call the N.memmap.__new__
A few comments about the wiki page: 1) The example does not show the printed info, such as "__new__ received %s", in the example session
OK, I'll edit the example
2) I don't understand, why in the example the "info" attribute is set in "__new__()", even though the text above says: """However, we need to keep in mind that any attribute that we define in the __new__ method will be shared among all the instances. If we want instance-specific attributes, we still need some specific initialization. We cannot use the __init__ method, as it won't be called. That's where __array_finalize__ comes to play."""
Yeah, that's not very clear. Well, look at the code of the example. In line 11, we call a view of the array, with our class as argument. That calls __array_finalize__, with "subarr" as the obj argument. __array_finalize__ sets a default "info" attribute: an empty dictionary, as the argumnet doesn't have an info attribute yet. In lines 14-18, we set the "info" argument of our object to the value we want.
3) the text about "The __array_finalize__ method" should at least once say that it is defined as "def __array_finalize__(self,obj)" -- otherwise I could only guess where the "obj" comes from.
OK, same as for 1.
4) related to the text after: "In other terms, __array_finalize__ is called" How do I know if a function or method actually invokes __new__ ;-) ? Would I have to study the numpy source ?
As a rule of thumb, __new__ is called each time you have a construction like MyClass(whatverargumentisneeded). When you rely on views (such as w/ the .view method, or ravel, or transpose...), you call __array_finalize__ . You don't really have to study the numpy code (even if it helps)
5) For the "__array_finalize__ method" there a text that says: """Subclasses inherit a default implementation of this method that does nothing""" --- but how about "__new__()" : what happens if you don't define that (either) ?
Try. The ndarray doesn't have a **keywords option: you can't pass extra parameters to ndarray.__new__. In other terms, if you need to pass some specific parameter to your class (in our example, info), you'll choke ndarray.
Hi Sebastian On Fri, Nov 23, 2007 at 09:25:37AM +0100, Sebastian Haase wrote:
Hi, this question might habe been answered before: I have my own ndarray-derived class. I did this, so that I can add another "custom attribute" -- let's say arr.filename All works very except, except when I do arr2 = arr.transpose() my arr2 is still of the *type* of my derived class, however trying a arr2.filename now gives me an AtttributeError.
What am I doing wrong? How can this be fixed? (I'm using numpy 1.0.1 - please let me know if this has been fixed since)
Show us the code, then we can take a look. I assume you have read http://www.scipy.org/Subclasses Regards Stéfan
participants (3)
-
Pierre GM
-
Sebastian Haase
-
Stefan van der Walt