我正在寻找创建一个动态包装类,它使用对象中的数据公开来自提供对象的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
,但我没见过
关于如何将所有这些放在一起的例子。
答案 0 :(得分:3)
您可以使用__getattr__
魔术方法来挂钩获取未定义的属性,并将它们转发到具体对象:
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()
答案 1 :(得分:1)
使用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