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. Спасибо за любые идеи!

0 ответов

Другие вопросы по тегам