Процесс инициализации группы классов, имеющих общего родителя, можно разделить на три части:
В настоящее время первые две части вызываются из метода __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()
в Subclass1
на __init__
(как в ответ С. Лотта ). Это облегчает жизнь, но все же нужно помнить, чтобы завершить инициализацию, на этот раз внутри «конструктора». В любом случае, нет способа обеспечить полную инициализацию, что я и ищу.
Версия 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
Шаблонный метод проектирования Шаблон для спасения:
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'
Аналогично подходу С. Лотта, за исключением того, что нет способа ( кроме переопределения __ 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"
Возможно, вы захотите предоставить реализацию по умолчанию , специфичную
в BaseClass
если не нормально вызывать AttributeError
при создании экземпляра любого подкласса, который не обеспечивает свою собственную реализацию.
Что не так с вызовом 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
Если вам нужно вызывать несколько методов в определенном порядке, это обычно означает, что у проекта есть проблемы с самого начала (это утечка деталей реализации). Поэтому я бы попытался работать с этой целью.
С другой стороны, если люди наследуют класс и должны изменить инициализацию, они должны знать о последствиях - это не то, что вы хотели бы иметь в своем обычном API. , В качестве альтернативы вы можете быть осторожны в отношении окончательной инициализации и проверить, что она вызывается в методах, которые зависят от нее (вызывать ее или вызывать исключение, если нет).