如何在继承的Python类中执行常见的后初始化任务?

Bor*_*lik 10 python inheritance initialization

共享一个共同父类的一组类的初始化过程可以分为三个部分:

  • 常用初始化
  • 子类特定的初始化
  • 常见的后期初始化

目前,前两个部分是从__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
Run Code Online (Sandbox Code Playgroud)

有没有办法不必调用finalizeInitialization()?或者可以将调用传递给finalizeInitialization()到Subclass1 finalizeInitialization()(如S.Lott的答案).这使得生活更轻松,但仍然需要记住完成初始化,这次是在"构造函数"中.无论哪种方式都没有办法强制执行完全初始化,这正是我正在寻找的.

Cam*_*lon 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() 
Run Code Online (Sandbox Code Playgroud)
base __init__
common 1
specific
finalizeInitialization [common2]
Run Code Online (Sandbox Code Playgroud)


Ale*_*lli 12

模板方法设计模式救援:

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'
Run Code Online (Sandbox Code Playgroud)


S.L*_*ott 10

版本1 - 委托一切.

class Subclass1(BaseClass):
    def __init__(self):
        super( Subclass1, self ).__init__()
        self.specific()
        super( Subclass1, self ).finalizeInitialization()
Run Code Online (Sandbox Code Playgroud)

版本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
Run Code Online (Sandbox Code Playgroud)