reckoner
reckoner

Reputation: 2981

how to dynamically generate methods for proxy class?

I have a object like:

class Foo(object):
    def __init__(self,instance):
        self.instance = instance

with

>>> instance = SomeOtherObject()
>>> f = Foo(instance)

I want to be able to do

>>> f.some_method()

and have the following call,

>>> f.instance.some_method()

For complicated reasons, I cannot simply chain the attributes as in the above. I need to dynamically create an instance function on f with the same function signature as the embedded instance. That is, I need to do f.some_method() and then dynamically create the some_method instance-method for the f instance when it is invoked that pushes some_method down to the embedded object instance.

I hope that made sense. This is for Python 2.7. Any help appreciated.

Upvotes: 0

Views: 1033

Answers (2)

kindall
kindall

Reputation: 184270

Write a __getattr__() method for your proxy class. This will be called when an attribute is accessed that doesn't exist on your instance. Return your contained object's attribute of the same name (or a wrapper if you insist, but there's no need if you just want to call the contained object's method and don't need to do anything else). Bonus: works with data as well as callables.

def __getattr__(self, name):
    return getattr(self.instance, name)

Does not work with __ methods, however.

Upvotes: 3

Graham Dumpleton
Graham Dumpleton

Reputation: 58563

You should look at the wrapt module. It is purpose built for creating transparent object proxy where you can selectively override certain aspects of the wrapped object. For example:

class Test(object):
    def some_method(self):
        print 'original'

import wrapt

proxy = wrapt.ObjectProxy(Test())
proxy.some_method()

print

class TestWrapper(wrapt.ObjectProxy):
    def some_method(self):
        self.__wrapped__.some_method()
        print 'override'

wrapper = TestWrapper(Test())
wrapper.some_method()

This yields:

original

original
override

The default behaviour of the ObjectProxy class is to proxy all method calls or attribute access. Updating attributes via the proxy will also update the wrapped object. Works for special __ methods and lots of other stuff as well.

For details on wrapt see:

Specific details on the object proxy can be found in:

There are so many traps and pitfalls with doing this correctly, so recommended you use wrapt if you can.

Upvotes: 1

Related Questions