在Python中链式调用父类初始化器

298 投票
3 回答
179876 浏览
提问于 2025-04-15 11:48

想象一下,有一个基础类A,类B从A继承,类C又从B继承。现在,怎么在一个类的初始化方法里通用地调用它父类的初始化方法呢?如果这个说法听起来有点模糊,下面有一些代码示例。

class A(object):
    def __init__(self):
        print "Initialiser A was called"

class B(A):
    def __init__(self):
        super(B,self).__init__()
        print "Initialiser B was called"

class C(B):
    def __init__(self):
        super(C,self).__init__()
        print "Initialiser C was called"

c = C()

这是我现在的做法。不过,这种方式似乎还是不够通用——你还是得手动传入正确的类型。

我试过用 self.__class__ 作为super()的第一个参数,但显然这样不行——如果你把它放在C的初始化方法里,B的初始化方法会被调用,这没问题。但如果你在B里也这么做,“self”仍然指向C的实例,所以你又会调用B的初始化方法,这样就会陷入无限循环。

现在不需要考虑菱形继承的问题,我只是想解决这个具体的问题。

3 个回答

29

你可以简单地写:

class A(object):

    def __init__(self):
        print "Initialiser A was called"

class B(A):

    def __init__(self):
        A.__init__(self)
        # A.__init__(self,<parameters>) if you want to call with parameters
        print "Initialiser B was called"

class C(B):

    def __init__(self):
        # A.__init__(self) # if you want to call most super class...
        B.__init__(self)
        print "Initialiser C was called"
218

Python 3 引入了一个改进版的 super(),让我们可以像这样使用它:

super().__init__(args)
170

你现在的做法确实是推荐的方式(适用于Python 2.x)。

关于是否要把类明确地传给super,这其实更多是风格上的问题,而不是功能上的问题。把类传给super符合Python的一个理念,那就是“明确总比隐含好”。

撰写回答