Правильный способ переопределения методов с незначительными изменениями в Python


Скажем, у меня есть класс

class Base(object):
    def my_method(self, input):
        print input #suppose this is many lines
        print "mymethod" #so is this

И подкласс, имеющий метод, который делает почти то же самое, за исключением дополнительной операции в середине метода, например

class Sub(Base):
    def mymethod(self, input): #how do I properly define this?
        print input 
        print "some other stuff" #additional operation in the middle
        print "mymethod" 

Каков правильный способ переопределения mymethod?

  • я копирую и вставляю большинство Base.mymethod()? (Вероятно, нет - это определенно нарушает сухой).
  • должен ли я определить Base.mymethod(), чтобы иметь условный оператор для дополнительной операции, которая возвращает true только в случае подкласса? (Вероятно, нет - это не имеет смысла, так как базовый класс должен быть автономным, и это похоже на рецепт катастрофы)
  • могу ли я как-то использовать super()? (Кажется, что нет - Sub дополнительная операция находится в середине метода, а не в начале или конце)
2 2

2 ответа:

Для такого простого примера я, скорее всего, скопирую эти три маленькие строки, даже если создам повторы. Старайтесь избегатьчрезмерной инженерии .

В случае, когда my_method() на самом деле сложнее, вы можете разделить свою функцию на три шага и позволить дочерним классам перегружать нужную им часть.

class Base(object):

    def my_method(self, input):
        self._preprocess(input)
        self._process()
        self._postprocess()

    def _preprocess(self, input):
        print(input)

    def _process(self):
        pass

    def _postprocess(self):
        print("mymethod")


class Sub(Base):

    def _process(self):
        print("some other stuff")

Конечно, вы должны использовать более осмысленные имена методов.

Это зависит от того, где вещи принадлежат. Обычно, если вы в конечном итоге хотите вставить материал между операциями метода базы, это означает, что метод на самом деле должен быть разделен на несколько методов.

Например:

class Base(object):
    def my_method(self, input):
        print input #suppose this is many lines
        print "mymethod" #so is this

Может стать:

class Base(object):
    def my_method(self, input):
        self.do_first_thing(input)
        self.do_second_thing("mymethod")

    def do_first_thing(self, input):
        print(input)

    def do_second_thing(self, data):
        print(data)
Это позволяет подклассам переопределять весь процесс без необходимости повторной реализации каждого шага. Эта концепция сродни шаблонному методу , но наоборот.

(обычно точкой шаблона метода pattern является чтобы позволить подклассам переопределить шаги, здесь мы используем ту же структуру, чтобы позволить подклассам переопределить сам шаблон).