代码之家  ›  专栏  ›  技术社区  ›  Boris Gorelik

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

  •  6
  • Boris Gorelik  · 技术社区  · 16 年前

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

    • 通用初始化
    • 子类特定的初始化
    • 公共post初始化

    目前前两部分是从 __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()?或者可以将finalizenitialization()的调用转移到子类1中 爱因斯坦 (如 S.Lott's answer )这使生活更容易,但仍然需要记住完成初始化,这次是在“构造函数”内部。无论哪种方法,都无法强制完全初始化,这正是我要寻找的。

    5 回复  |  直到 6 年前
        1
  •  7
  •   S.Lott    16 年前

    版本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
    
        2
  •  12
  •   Alex Martelli    16 年前

    救援模板方法设计模式:

    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'
    
        3
  •  1
  •   Robert Rossney    16 年前

    类似于S.Lott的方法,除了没有办法(除了 __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 当您创建不提供自己实现的任何子类的实例时。

        4
  •  0
  •   Eric Palakovich Carr    16 年前

    从子类的init调用finalitilazation有什么问题?

       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
    
        5
  •  0
  •   nikow    16 年前

    如果必须以特定的顺序调用多个方法,通常意味着设计开始时有问题(它泄漏了实现细节)。所以我会努力从这一点开始工作。

    另一方面,如果人们从类中派生,并且必须修改初始化,那么他们应该知道其含义——这不是您希望在常规API中使用的内容。或者,您可以对最后的初始化进行防御,并检查是否在依赖它的方法中调用了它(如果没有调用它或引发异常)。