__init__可以在调用super之后自动执行代码吗?

时间:2019-04-29 14:32:10

标签: python

我有这样的东西:

class SuperClass(object):
    def __init__(self):
        # initialization stuff

    def always_do_this_last(self):
        # cleanup stuff


class SubClass(SuperClass):
    def __init__(self):
        super().__init__()
        # intermediate stuff
        self.always_do_this_last()

是否可以自动拨打最后一行? SuperClass的每个子类都需要执行清理。

4 个答案:

答案 0 :(得分:2)

您有2个选择:

  1. 使用其他方法作为初始化程序,然后调用always_do_this_last

    class SuperClass(object):
        def __init__(self):
            self._init()  # initialize
            self.always_do_this_last()  # clean up
    
        def _init(self):
            pass # initialization stuff
    
        def always_do_this_last(self):
            pass # cleanup stuff
    
    class SubClass(SuperClass):
        def _init(self):
            super()._init()
            # intermediate stuff
    
  2. 使用metaclass

    class CleanupMeta(type):
        def __call__(cls, *args, **kwargs):
            obj = super().__call__(*args, **kwargs)
            obj.always_do_this_last()
            return obj
    
    class SuperClass(metaclass=CleanupMeta):
        def __init__(self):
            pass # initialization stuff
    
        def always_do_this_last(self):
            pass # cleanup stuff
    
    class SubClass(SuperClass):
        def __init__(self):
            super().__init__()
            # intermediate stuff
    

答案 1 :(得分:2)

定义而不是覆盖__init__的方法是定义SuperClass.__init__将调用的方法。

class SuperClass(object):
    def __init__(self):
        # do some stuff
        self.child_init()
        self.cleanup()

    def cleanup():
        ...

    def child_init(self):
        pass


class SubClass(SuperClass):
    def child_init(self):
        ...

您可以定义SuperClass.__init_subclass__以确保覆盖child_init,或使用abc模块将SuperClass.child_init用作抽象方法

答案 2 :(得分:1)

一个选择可能是使用子类可以覆盖而不覆盖__init__()的方法。也许像这样:

class SuperClass:
    def __init__(self):
        # initialization stuff
        self.setup_subclass()
        self.always_do_this_last()

    def setup_subclass(self):
        pass

    def always_do_this_last(self):
        # cleanup stuff

class SubClass(SuperClass):
    def setup_subclass(self):
        # intermediate stuff

对您有用吗?

答案 3 :(得分:1)

这里的其他答案绰绰有余。我还要补充一点,如果您正在实现一个需要实现某些成员函数的类,那么您可能想看看abstract base class

在下面的示例中,父级要求在每个子级中定义initializecleanup方法(尝试删除其中的一个以验证是否出现错误)。

import abc

class SuperClass(object):

    __metaclass__ = abc.ABCMeta

    def __init__(self):
        print("Instantiating Class")
        self.initialize()
        self.cleanup()

    @abc.abstractmethod
    def initialize(self):
        pass

    @abc.abstractmethod
    def cleanup(self):
        pass

class SubClass(SuperClass):
    def __init__(self):
        super(SubClass, self).__init__()

    def initialize(self):
        print("initializing...")

    def cleanup(self):
        print("... cleanup.")


a = SubClass()