如何动态生成代理类的方法?

时间:2016-08-05 00:58:01

标签: python metaprogramming

我有一个像这样的对象:

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

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

我希望能够做到

>>> f.some_method()

并进行以下调用,

>>> f.instance.some_method()

由于复杂的原因,我不能简单地链接上面的属性。我需要在f上动态创建一个具有与嵌入式instance相同的函数签名的实例函数。也就是说,我需要执行f.some_method(),然后在some_method实例被调用时将动态创建f实例方法,将some_method向下推送到嵌入对象{ {1}}。

我希望这是有道理的。这适用于Python 2.7。任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:3)

为您的代理类编写__getattr__()方法。当访问在您的实例上不存在的属性时,将调用此方法。返回您所包含的同名对象的属性(如果您坚持,则返回包装器,但如果您只是想调用所包含的对象的方法并且不需要,则不需要做其他事情)。奖励:适用于数据和可调用的内容。

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

但不适用于__方法。

答案 1 :(得分:1)

您应该查看wrapt模块。它的目的是创建透明对象代理,您可以有选择地覆盖包装对象的某些方面。例如:

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()

这会产生:

original

original
override

ObjectProxy类的默认行为是代理所有方法调用或属性访问。通过代理更新属性也将更新包装对象。适用于特殊的__方法以及许多其他方法。

有关wrapt的详细信息,请参阅:

有关对象代理的具体详情,请参阅:

正确执行此操作有很多陷阱和陷阱,因此建议您尽可能使用wrapt