在python中,可以编写一个在子类的__init__之后自动调用的方法

时间:2014-03-07 22:15:56

标签: python subclass

我正在写一个其他人使用的库。

对于每个重要的功能,我都有一个基类。用户应该将这些子类化,并添加他们的重要方法版本。

现在我想我需要添加一个“setup()”函数,该函数必须在子类的 init ()之后运行,但是Problem已经存在不同的子类,我不想让人们触摸那些。

我也在2.7上发展。

说:

class Problem:
    def __init__(self,**kwargs):
        #this and that

    def setup(self,**kwargs):
        #Generic stuff that needs to be done after SpecificProblem.__init__() is called.

class SpecificProblem(Problem):
    def __init__(self,**kwargs):
        Problem.__init__(self,**kwargs)
        #this and that

3 个答案:

答案 0 :(得分:8)

不应让子类覆盖__init__,而应让他们编写一个名为make的方法。如:

class Problem:
    def __init__(self,**kwargs):
        self.make(**kwargs)
        self.setup(**kwargs)

    def setup(self,**kwargs):
        #Generic stuff that needs to be done after SpecificProblem.__init__() is called.

    def make(self,**kwargs):
        # method to be overwritten by subclasses
        pass

class SpecificProblem(Problem):
    def make(self,**kwargs):
        #this and that

这个问题有不同的方法。如果您希望编写SpecificProblem的人负责完成所有操作以及完成任务,那么元类方法就有意义。但是,如果你想要适当地“分开关注点”,那么我的方式允许你这样做。

答案 1 :(得分:4)

gabe的回答是你应该使用的,但这是一个适合元类的问题;没有进一步阐述:

class SetupClass(type):
    def __call__(cls, *args, **kwargs):
        # create the instance as normal.  this will invokoe the class's
        # __init__'s as expected.
        self = super(SetupClass, cls).__call__(*args, **kwargs)

        # this steps through the MRO in ascending order (so that child
        # classes can be confident their bases are "set up").  A corresponding
        # teardown() method should probably be `reversed(cls.__mro__)`
        for base in cls.__mro__:
            setup = vars(base).get('setup')
            # in the general case, we have to use the descriptor protocol
            # to setup methods/staticmethods/classmethods properly
            if hasattr(setup, '__get__'):
                setup = setup.__get__(self, cls)
            if callable(setup):
                setup()

        return self

class A(object):
    __metaclass__ = SetupClass
    def __init__(self):
        print "A.__init__"
    def setup(self):
        print "A.setup"
class B(A):
    def __init__(self):
        print "B.__init__"
        super(B, self).__init__()
>>> B()
B.__init__
A.__init__
A.setup

答案 2 :(得分:0)

只需拨打Problem.setup

__init__中的SpecificProblem即可
class SpecificProblem(Problem):
    def __init__(self,**kwargs):
        Problem.__init__(self,**kwargs)
        #this and that
        Problem.setup(self, **kwargs)   

你应该真正在python中使用新式的类,因为它们是python 3.x中的默认类。

class Problem(object):
    def __init__(self, **kwargs):
        pass
    def setup(self, **kwargs):
        pass

class SpecificProblem(Problem):
    def __init__(self, **kwargs):
        super(SpecificProblem, self).__init__(**kwargs)
        # In python three, super().__init__(**kwargs) works.
        super(SpecificProblem, self).setup(**kwargs)