[Tutor] dynamic proxy in python oop

Danny Yoo dyoo@hkn.eecs.berkeley.edu
Sat, 6 Jul 2002 11:34:29 -0700 (PDT)


On Sat, 6 Jul 2002, Ashish wrote:

> hi just a question on python oop!
>
> i want to make a proxy class that will call the function in another
> class when its functions are called.
>
> proxyObject.doSomething() should call realObject.doSomething()
>
> I don't want to define doSomething() in proxy class as i want to be able
> to change real class as i want and i am not sure about the functions
> that real class will have till runtime.

Yes, this is possible using Python.  In the expression:

    proxyObject.doSomething()

Python actually does at least two things when it sees this expression: it
looks up the 'doSomething' attribute on our proxyObject, because even
methods are attributes in Python.  Only after this, after grabbing the
method out of the object, can we call it.


We can modify the attribute lookup of any class by writing a special
method called '__getattr__'.  Here's an example:

###
class ProxyClass:
    def __init__(self, real_object):
        self.real_object = real_object

    def __getattr__(self, attribute):
	return getattr(self.real_object, attribute)
###

This ProxyClass says that any attribute lookup on a ProxyClass will
actually delegate off to the real_object.

Here's a concrete example of how this might work:

###
>>> class Person:
...     def sayHello(self):
...         print "Hello!"
...     def wipe(self):
...         print "Your face is already clean"
...
>>> some_person = Person()
>>> some_person.sayHello()
Hello!
>>> proxied_person = ProxyClass(some_person)
>>> proxied_person.sayHello()
Hello!
>>> proxied_person.wipe()
Your face is already clean
>>> some_person.sayHello
<bound method Person.sayHello of <__main__.Person instance at 0x8150b14>>
>>> proxied_person.sayHello
<bound method Person.sayHello of <__main__.Person instance at 0x8150b14>>
>>> proxied_person.jump
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 5, in __getattr__
AttributeError: Person instance has no attribute 'jump'
###


Alex Martelli wrote a really cool post about an alternative way of making
one class instance look like another one:

    http://groups.google.com/groups?selm=8ubclp01s4t%40news1.newsguy.com

which I think you might enjoy.



Hope this helps!