Python:包装器隐藏多个类实例以实现向后兼容性

时间:2018-08-06 08:50:42

标签: python-3.x class refactoring wrapper multiple-instances

我有以下情况。考虑一个只有一个酒吧的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实例。 感谢您的任何想法!

0 个答案:

没有答案