Re: [Tutor] class instance with identity crisis
My opinion is : this is a very dangerous and stupid thing to do !!! Try to imagine the complexity of your program for someone who is trying to understand how your code is working if an object suddenly change its own type !!! Clearly, if you want to change the type of an object, you want a conversion method (or function) and creates a new object (that's what you'll do anyway). If you don't need the old object anymore, you can just reuse the variable name. Then, it's impossible to achieve in Python (at least in the general case ... you could do it with pure Python objects). And I hope it will forever remain impossible ! And last, I think you misunderstood the behaviour of the assignment statement in Python. In no way an assignement will overwrite an existing value. It will simply make the variable assigned point on another object. The consequence is, if there are many variables pointing on the same object, reassigning one of them will not affect the other ones. So when you write self = Prune() you don't change the variable the user holds but only the local self variable, variable that will disappear at the end of the method and so your Prune object will be discarded. I hope my last paragraph is clear (but I don't think so :D). Pierre Barnaby Scott a écrit : This is probably a very easy question, and one that I was shocked to find I was stuck on, having thought I understood classes! I was wondering how you can get an instance of a class to change itself into something else (given certain circumstances), but doing so from within a method. So: class Damson: def __str__(self): return 'damson' def dry(self): self = Prune() class Prune: def __str__(self): return 'prune' weapon = Damson() weapon.dry() print weapon All the old hands will of course know this will produce the output damson but something in me suggests it should produce prune After all, 'self' refers to the instance 'weapon'. Obviously one could reassign weapon to a Prune outside the class definition, but I was hoping to write something in which, given certain circustances arising, the instance would change itself into something else. Time to go back to school! ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor -- Pierre Barbier de Reuille INRA - UMR Cirad/Inra/Cnrs/Univ.MontpellierII AMAP Botanique et Bio-informatique de l'Architecture des Plantes TA40/PSII, Boulevard de la Lironde 34398 MONTPELLIER CEDEX 5, France tel : (33) 4 67 61 65 77fax : (33) 4 67 61 56 68 ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class instance with identity crisis
A couple of ideas: You could have dry() return the new weapon: def dry(self): return Prune() then the client code would be weapon = weapon.dry() You could have the weapon encapsulate another object and delegate to it. Finally, you actually can change the class of an object just by assigning to self.__class__: class A: ... def show(self): ... print I'm an A ... class B: ... def show(self): ... print I'm a B ... a=A() a.__class__ class __main__.A at 0x008CE750 a.show() I'm an A a.__class__ = B type(a) type 'instance' a.show() I'm a B So if you change self = Prune() to self.__class__ = Prune I think you will get the behaviour you are looking for. I would look for another way to solve your problem, though - I agree with Pierre that this is likely to be confusing. Kent Barnaby Scott wrote: This is probably a very easy question, and one that I was shocked to find I was stuck on, having thought I understood classes! I was wondering how you can get an instance of a class to change itself into something else (given certain circumstances), but doing so from within a method. So: class Damson: def __str__(self): return 'damson' def dry(self): self = Prune() class Prune: def __str__(self): return 'prune' weapon = Damson() weapon.dry() print weapon All the old hands will of course know this will produce the output damson but something in me suggests it should produce prune After all, 'self' refers to the instance 'weapon'. Obviously one could reassign weapon to a Prune outside the class definition, but I was hoping to write something in which, given certain circustances arising, the instance would change itself into something else. Time to go back to school! ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class instance with identity crisis
On Wednesday 12 January 2005 12:10, Kent Johnson wrote: A couple of ideas: You could have dry() return the new weapon: def dry(self): return Prune() then the client code would be weapon = weapon.dry() You could have the weapon encapsulate another object and delegate to it. As an alternative solution, you could use the Proxy pattern; this approach has the advantage that there is no dynamic reassignment of the __class__ attribute. The following program shows what I mean: class Apple: def whoami(self): print I am an apple! def __str__(self): return Apple class Egg: def whoami(self): print I am an egg! def __str__(self): return Egg class Proxy: def __init__(self): self.delegate = Apple() self.is_apple = True def __getattr__(self, attr): return getattr(self.delegate, attr) def change(self): if self.is_apple: self.delegate = Egg() else: self.delegate = Apple() self.is_apple = not self.is_apple if __name__ == __main__: thing = Proxy() thing.whoami() print thing thing.change() thing.whoami() print thing thing.change() thing.whoami() print thing This will give the following output: I am an apple! Apple I am an egg! Egg I am an apple! Apple The magic here lies in the __getattr__ (note the double underscores) method; whenever the Proxy is asked for an attribute (such as a method), it delegates this question to the self.delegate. Alternatively, if the __getattr__ is a bit too much magic, you could also duplicate the attributes that you actually want to expost: class Proxy: def __init__(self): # as above def whoami(self): self.delegate.whoami() def __str__(self): return str(self.delegate) def change(self): # as above As others have stated, you should use this pattern with care. On the other hand, I do believe that there are instances when this can be useful, as long as the delegates have more or less the same interface (the same attributes). Yigal ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class instance with identity crisis
On Wed, 12 Jan 2005, Barnaby Scott wrote: I was wondering how you can get an instance of a class to change itself into something else (given certain circumstances), but doing so from within a method. So: class Damson: def __str__(self): return 'damson' def dry(self): self = Prune() class Prune: def __str__(self): return 'prune' weapon = Damson() weapon.dry() print weapon Hi Scott, The issue with that, as you know, is that it conflicts with the way local variables work in functions. For example: ### def strip_and_print(x): ... x = x.strip() ... print x ... message =hello strip_and_print(message) hello message ' hello ' ### Our reassignment to 'x' in strip_and_print has no effect on message's binding to hello . That's how we're able to use local variables as black boxes. For the same reasons, the reassignment to 'self in: class Damson: def __str__(self): return 'damson' def dry(self): self = Prune() is limited in scope to the dry() method. But can you do what you're trying to do with object composition? That is, would something like this work for you? ### class Damson: def __init__(self): self.state = DamsonState() def __str__(self): return str(self.state) def dry(self): self.state = PruneState() class DamsonState: def __str__(self): return damson class PruneState: def __str__(self): return 'prune' ### This structuring allows us to switch the way that str() applies to Damson. The OOP Design Pattern folks call this the State pattern: http://c2.com/cgi/wiki?StatePattern If you have any questions, please feel free to ask! ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class instance with identity crisis
My opinion is : this is a very dangerous and stupid thing to do !!! No its quite common. Its why C++ for example allows you to write your own type convcersion functions! One area where I've used this is to convert faults to orders in a service management application. Its fairly common for a customer to report a fault which then turns out to be due to a missing extra that theynneed to order. The conversion function then copies all the captured order details (cust ID and description etc) into a new fault object and returns a reference to that. own type !!! Clearly, if you want to change the type of an object, you want a conversion method (or function) and creates a new object (that's But this is true, changing the actual instance under the covers is a bad idea. And last, I think you misunderstood the behaviour of the assignment statement in Python. In no way an assignement will overwrite an existing value. It will I hope my last paragraph is clear (but I don't think so :D). Well I understood it OK :-) Alan G. ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
RE: [Tutor] class instance with identity crisis
Thanks to all who responded. I see my biggest mistake was not spotting the assignment of 'self' being local to the method - very dumb indeed, especially as I have seen this many times before. However I am glad I was not necessarily dumb to want to do what I was thinking of. I am learning lots! Thanks -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] Behalf Of Alan Gauld Sent: 12 January 2005 20:13 To: Alan Gauld; Barnaby Scott; 'Tutor' Subject: Re: [Tutor] class instance with identity crisis Whoops, I forgot to do an assignment... So try def dry(self): return Prune() class Prune: def __str__(self): return 'prune' weapon = Damson() weapon.dry() weapon = weapon.dry() print weapon Should work as expected... Alan G ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor