Как выполнять общие задачи после инициализации в унаследованных классах Python? - PullRequest
6 голосов
/ 28 апреля 2009

Процесс инициализации группы классов, имеющих общего родителя, можно разделить на три части:

  • Общая инициализация
  • Инициализация для подкласса
  • Обычная пост-инициализация

В настоящее время первые две части вызываются из метода __init__ каждого дочернего класса, но последняя часть после инициализации должна вызываться отдельно, например

class BaseClass:
    def __init__(self):
    print 'base __init__'
    self.common1()

    def common1(self):
    print 'common 1'

    def finalizeInitialization(self):
    print 'finalizeInitialization [common2]'


class Subclass1(BaseClass):
    def __init__(self):
    BaseClass.__init__(self)
        self.specific()

    def specific(self):
    print 'specific'


if __name__ == '__main__':
    s = Subclass1() #Don't forget to finalize the initialization
    s.finalizeInitialization()  # now the object is fully initialized

Есть ли способ не вызывать finalizeInitialization ()? Или можно перевести вызов finalizeInitialization () в __init__ из Subclass1 (как в ответе S.Lott ). Это облегчает жизнь, но все же нужно помнить, чтобы завершить инициализацию, на этот раз внутри «конструктора». В любом случае, нет способа обеспечить полную инициализацию, что я и ищу.

Ответы [ 5 ]

12 голосов
/ 28 апреля 2009

Шаблонный метод проектирования Шаблон для спасения:

class BaseClass:
    def __init__(self, specifics=None):
        print 'base __init__'
        self.common1()
        if specifics is not None:
            specifics()
        self.finalizeInitialization()

    def common1(self):
        print 'common 1'

    def finalizeInitialization(self):
        print 'finalizeInitialization [common2]'


class Subclass1(BaseClass):
    def __init__(self):
        BaseClass.__init__(self, self.specific)

    def specific(self):
        print 'specific'
8 голосов
/ 28 апреля 2009

Версия 1 - делегировать все.

class Subclass1(BaseClass):
    def __init__(self):
        super( Subclass1, self ).__init__()
        self.specific()
        super( Subclass1, self ).finalizeInitialization()

Версия 2 - делегировать только один шаг

class BaseClass:
    def __init__(self):
        print 'base __init__'
        self.common1()
        self.specific()
        self.finalizeInitialization()

    def common1(self):
        print 'common 1'

    def finalizeInitialization(self):
        print 'finalizeInitialization [common2]'

    def specific( self ):
        # two choices:
        # if this is "abstract": raise an exception
        # if this is "concrete": pass
1 голос
/ 28 апреля 2009

Аналогичен подходу С. Лотта, за исключением того, что нет никакого способа (кроме переопределения __init__) для производных классов переопределить (или даже вызвать) общие методы:

class BaseClass:
    def __init__(self):
        def common():
            print "common initialization..."

        def final():
            print "common finalization..."

        common()
        self.specific()
        final()

    def final_init(self):
        print "BaseClass.final_init"


class Subclass1(BaseClass):

    def specific(self):
        print "Subclass1.specific"

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

0 голосов
/ 28 апреля 2009

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

С другой стороны, если люди наследуют класс и должны изменить инициализацию, они должны знать о последствиях - это не то, что вы хотели бы иметь в своем обычном API. В качестве альтернативы вы можете быть осторожны в отношении окончательной инициализации и проверить, что она была вызвана в методах, которые зависят от нее (чтобы вызвать или вызвать исключение, если нет).

0 голосов
/ 28 апреля 2009

Что не так с вызовом finalInitilazation из init подкласса?

   class BaseClass:
        def __init__(self):
            print 'base __init__'
            self.common1()

        def common1(self):
            print 'common 1'

        def finalizeInitialization(self):
            print 'finalizeInitialization [common2]'


    class Subclass1(BaseClass):
        def __init__(self):
            BaseClass.__init__(self)
            self.specific()
            BaseClass.finalizeInitialization(self)

        def specific(self):
            print 'specific'


    if __name__ == '__main__':
        s = Subclass1() #Don't forget to finalize the initialization
        s.finalizeInitialization()  # now the object is fully initialized
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...