如何在继承类中执行常见的后初始化任务?
一组有共同父类的类的初始化过程可以分为三个部分:
- 共同初始化
- 子类特定初始化
- 共同后初始化
目前,前两个部分是在每个子类的 __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__
方法里(就像在S.Lott的回答中提到的)。这样做会让事情变得简单一些,但仍然需要记得在“构造函数”里完成初始化。无论如何,都没有办法强制执行完整的初始化,这正是我想要的。
6 个回答
14
模板方法设计模式来帮忙了:
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'
15
你可以使用元类(这里的代码已经更新到Python3版本):
class PostInitCaller(type):
def __call__(cls, *args, **kwargs):
obj = type.__call__(cls, *args, **kwargs)
obj.__post_init__()
return obj
class BaseClass(metaclass=PostInitCaller):
def __init__(self):
print('base __init__')
self.common1()
def common1(self):
print('common 1')
def finalizeInitialization(self):
print('finalizeInitialization [common2]')
def __post_init__(self): # this is called at the end of __init__
self.finalizeInitialization()
class Subclass1(BaseClass):
def __init__(self):
super().__init__()
self.specific()
def specific(self):
print('specific')
s = Subclass1()
base __init__
common 1
specific
finalizeInitialization [common2]
10
版本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