Python: оболочка для скрытия нескольких экземпляров классов для обратной совместимости
У меня следующая ситуация. Рассмотрим Фу, у которого был один Бар. Таким образом, класс был реализован для 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 может иметь два или более столбцов, и новый 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. Спасибо за любые идеи!