Python 中的动态包装器



我希望创建一个动态包装类,该类使用对象中的数据公开来自提供对象的 API 调用。

静态地看起来像这样:

 class Concrete:
     def __init__(self, data):
       self.data = data
     def print_data(self):
         print(self.data)

 class Wrapper:
     '''
     One day this will wrap a variety of objects. But today
     it can only handle Concrete objects.
     '''
     def wrap_it(self, concrete):
         self.cco = concrete  # concreteobject=cco
     def print_data(self):
         self.cco.print_data()

 cco = Concrete(5)
 wcco = Wrapper()
 wcco.wrap_it(cco)
 wcco.print_data()

生产

 5

我想弄清楚如何做同样的事情,但让 wrap_it动态的。它应该搜索具体对象查找函数,并创建同名函数在具体对象中调用相同的函数。

我想解决方案涉及inspect.signature或至少使用*args**kwargs,但我还没有看到一个关于如何将所有这些放在一起的示例。

您可以使用 __getattr__ magic 方法来挂钩获取未定义的属性,并将它们转发到具体对象:

class DynamicWrapper():
    def wrap_it(self, concrete):
        self.cco = concrete
    def __getattr__(self, k):
        def wrapper(*args, **kwargs):
            print(f'DynamicWrapper calling {k} with args {args} {kwargs}')
            return getattr(self.cco, k)(*args, **kwargs)
        if hasattr(self.cco, k):
            return wrapper
        else:
            raise AttributeError(f'No such field/method: {k}')
cco = Concrete(5)
dwcco = DynamicWrapper()
dwcco.wrap_it(cco)
dwcco.print_data()

使用 dir(( 函数获取给定对象的属性,检查它们是否可调用并将它们分配给包装器,如下所示:

 class Wrapper:
     def wrap_it(self, objToWrap):
         for attr in dir(objToWrap):
             if not attr.startswith('__') and callable(getattr(objToWrap, attr)):
                 exec('self.%s = objToWrap.%s' % (attr, attr))

现在,用于测试。

>>> cco = Concrete(5)
>>> wcco = Wrapper()
>>> wcco.wrap_it(cco)
>>> wcco.print_data()
5

最新更新