我正在寻找一种方法来收集同类对象,将它们包装在另一个对象中,但使包装对象具有与原始对象相同的API,并将相应的API调用转发给其对象成员。
class OriginalApi:
def __init__(self):
self.a = 1
self.b = "bee"
def do_something(self, new_a, new_b, put_them_together=None):
self.a = new_a or self.a
self.b = new_b or self.b
if put_them_together is not None:
self.b = "{}{}".format(self.a, self.b)
# etc.
class WrappedApi:
def __init__(self):
self.example_1 = OriginalApi()
self.example_2 = OriginalApi()
Run Code Online (Sandbox Code Playgroud)
已经考虑了一些可能的解决方案,但是这些解决方案还不够充分:
重写整个API,为什么不呢?由于API相当大且正在扩展,因此还不够。必须在多个位置维护API是不现实的。
代码示例:
class WrappedApi:
def __init__(self):
self.example_1 = OriginalApi()
self.example_2 = OriginalApi()
def do_something(self, new_a, new_b, put_them_together=None):
self.example_1.do_something(new_a, new_b, put_them_together)
self.example_2.do_something(new_a, new_b, put_them_together)
Run Code Online (Sandbox Code Playgroud)使用列表和for循环这将更改对象上的API。就是说,这是我无法找到更优雅的解决方案。在这种情况下,WrappedApi
该类将不存在。
代码示例:
wrapped_apis = [OriginalApi(), OriginalApi()]
for wrapped_api in wrapped_apis:
wrapped_api.do_something(1, 2, True)
Run Code Online (Sandbox Code Playgroud)我尝试使用 Python Object Wrapper,但是看不到如何用相同的参数调用多个子对象。
对于对用例感到好奇的人,它实际上是几个matplotlib axes
对象的集合。我不想重新实现对整个axes
API(它的大),我不想改变这一切,使中轴线上调用的代码(如plot
,step
等)
如果您仅实现方法,那么泛型__getattr__
就可以解决问题
class Wrapper:
def __init__(self, x):
self.x = x
def __getattr__(self, name):
def f(*args, **kwargs):
for y in self.x:
getattr(y, name)(*args, **kwargs)
return f
Run Code Online (Sandbox Code Playgroud)
例如,x = Wrapper([[], [], []])
调用后,x.append(12)
所有三个列表对象的最后一个元素将为12。
请注意,返回值将始终为None
...一个选项可以收集返回值并将其作为列表返回,但这当然会“破坏API”。