Python: написание оболочки вокруг стороннего класса - PullRequest
2 голосов
/ 19 января 2011

Мне нужны некоторые функции из класса X стороннего модуля m. Я мог бы просто использовать m.X напрямую, но в будущем мне может понадобиться заменить m.X на другой класс n.Y (например, если я найду лучшую реализацию).

Я бы хотел избежать изменения остальной части кода в такой ситуации.

Сейчас я хочу, чтобы полный интерфейс m.X, включая инициализацию, проходил без изменений. Я написал обертку W для m.X следующим образом:

class W(m.X):
    def __init__(self, *args):
        super().__init__(*args)

В будущем, если возникнет такая необходимость, я планирую переписать вышеприведенное как:

class W(n.Y):
    def __init__(self, *args):
        super().__init__(*args)
    # override instance methods of n.Y that don't share the semantics with m.X
    # for example, in case f1 is hard to replicate in n.Y:
    # def f1(self, *args):
    #     print("this method is no longer available")
    #     raise MyDeprecatedMethod()
    # for example, in case f2 needs to be recalculated
    # def f2(self, *args):
          # do the calculations required to keep W.f2 unchanged 

Допустим ли мой текущий упаковщик для m.X? Есть ли проблемы с ним или с запланированной оберткой для n.Y?

Ответы [ 3 ]

3 голосов
/ 19 января 2011

Вы можете просто использовать

class W(m.X):
    pass

, который наследует m.X.__init__() по умолчанию.

2 голосов
/ 19 января 2011

Самый простой способ - написать:

W = m.X

Практически все в Python является первоклассным объектом, включая типы. Класс практически неотличим от любой другой переменной, например:

def W(*args, **kwargs):
    return m.X(*args, **kwargs)

может создать экземпляр экземпляра m.X, при этом указав, что W является его фактическим именем. (Обратите внимание, что с этим методом isinstance не будет работать правильно - он будет работать нормально с первым примером.)

В некоторых случаях использование назначений может не совсем подходить для IDE. В этом случае:

class W(m.X): pass

также даст тот же результат, хотя с добавленными издержками в этом случае W являются только экземплярами m.X, поскольку W является подклассом: использование W=m.X; W(args) создаст экземпляр m.X.

0 голосов
/ 01 мая 2017

Это будет зависеть от того, насколько отличаются m.X и n.Y в используемых вами методах, но это может быть так же просто, как

try:
    import n.Y as foo
except ImportError:
    import m.X as foo

class W(foo):
    pass

так что ваш код автоматически отражает новый модуль, потенциально сводя к минимуму изменения, которые необходимо внести в вашу кодовую базу.

...