Re: [Tutor] class instance with identity crisis

2005-01-12 Thread Pierre Barbier de Reuille
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

2005-01-12 Thread Kent Johnson
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

2005-01-12 Thread Yigal Duppen
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

2005-01-12 Thread Danny Yoo


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

2005-01-12 Thread Alan Gauld

 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

2005-01-12 Thread Barnaby Scott
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