我有以下情况。考虑一个只有一个酒吧的Foo。因此,已经为Bar实现了一个类,而Foo拥有一个bar成员,并且都可以这样使用:
class Bar:
def __init__(self, name):
self.name = name
def doit(self):
print('%s doing stuff' % self.name)
class Foo:
def __init__():
self.bar = Bar('duck')
foo = Foo()
foo.bar.doit()
>> duck doing stuff
现在,由于某些不可预见的原因,新版本的Foo可以具有两个或多个Bar,并且新的API应该是这样的:
foo.bar.channel0.doit()
foo.bar.channel1.doit()
但是,旧的约定仍然有效:
foo.bar.doit() # shall be equivalent with foo.bar.channel0.doit()
我可以通过以下方式实现以下目的:
class BarWrapper:
def __init__(self):
self.bar_list: List[Bar] = []
def addInstance(self, bar: Bar):
self.bar_list.append(bar)
def __getattribute__(self, name):
"""
Fallback to chanel 0
:param name: attribute name to be accessed
:return: self's attribute, if exist, else fallback to channel0's attributes
"""
try:
return object.__getattribute__(self, name)
except AttributeError:
return self.bar_list[0].__getattribute__(name)
@property
def channel0(self) -> Bar:
return self.bar_list[0]
@property
def channel1(self) -> Bar:
return self.bar_list[1]
class Foo:
def __init__(self):
# self.bar = Bar('duck')
self.bar = BarWrapper()
self.bar.addInstance(Bar('duck'))
self.bar.addInstance(Bar('cat'))
foo = Foo()
foo.bar.channel0.doit()
>> duck doing stuff
foo.bar.doit()
>> duck doing stuff
foo.bar.channel1.doit()
>> cat doing stuff
我的问题是:这周围是否还有更优雅的方式?这样做的一个问题是,现在代码完成不能与foo.bar一起使用,因为它现在是BarWrapper实例,而不是Bar实例。 感谢您的任何想法!