[Tutor] class instance with identity crisis

Yigal Duppen yduppen at xs4all.nl
Wed Jan 12 12:31:37 CET 2005


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



More information about the Tutor mailing list