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

22 投票
6 回答
20176 浏览
提问于 2025-04-15 11:17

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

  • 共同初始化
  • 子类特定初始化
  • 共同后初始化

目前,前两个部分是在每个子类的 __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

撰写回答