超级初始化与父级.__ init__

时间:2015-03-20 18:20:09

标签: python python-2.7 inheritance

可以使用或不调用super()来初始化Python子类,如下所示

class Parent(object):
    ...

class Child(Parent):

    def __init__(self):
        super(Child, self).__init__()


class Child(Parent):

    def __init__(self):
        Parent.__init__(self)

这些案件之间有什么区别,并且通常比另一案件更受欢迎?

2 个答案:

答案 0 :(得分:24)

超级的目的是处理继承钻石。如果上课 继承结构只使用单继承,然后使用super()将 导致与显式调用" parent"相同的调用。类。

考虑这个继承钻石:

class A(object):
    def __init__(self):
        print('Running A.__init__')
        super(A,self).__init__()

class B(A):
    def __init__(self):
        print('Running B.__init__')        
        super(B,self).__init__()

class C(A):
    def __init__(self):
        print('Running C.__init__')
        super(C,self).__init__()

class D(B,C):
    def __init__(self):
        print('Running D.__init__')
        super(D,self).__init__()

foo = D()

打印

Running D.__init__
Running B.__init__
Running C.__init__
Running A.__init__

如果我们将B更改为B2并使用对父__init__的显式调用:

class B2(A):
    def __init__(self):
        print('Running B.__init__')        
        A.__init__(self) 

class D2(B2,C):
    def __init__(self):
        print('Running D.__init__')
        super(D2,self).__init__()

bar = D2()

然后init调用链变为

Running D.__init__
Running B.__init__
Running A.__init__

因此完全跳过对C.__init__的调用。


没有一个首选方案。

如果您可以保证您不想支持多重继承 显式父调用更简单,更清晰。

如果您希望现在或将来支持多重继承,则需要使用super()。但是要明白使用super会涉及some pitfalls,但是proper use可以避免这些陷阱。

答案 1 :(得分:8)

super(Child, self).__init__(self)的主要目的是允许在使用菱形继承结构进行多重继承的情况下正确运行初始化。如果显式调用具有多个继承的基类构造函数,则可能会调用两次初始化程序。使用单继承,使用super和显式调用基类__init__()方法之间没有功能差异。请注意,因为所有python新样式类都是子类对象,所以多重继承总是涉及钻石继承。

如果重命名或更改基类,

super减少需求更改的好处较小。

在python 3中,super的参数是可选的,因此你可以super().__init__(self)。 Python 2仍然要求您明确提供参数。