有什么不同?SomeBaseClass.__init__(self)

意味着调用SomeBaseClass的__init__。而

super(Child, self).__init__()

意味着__init__从Child实例的方法解析顺序中的父类调用一个绑定。

如果实例是Child的一个子类,则在方法解析顺序中可能会有另一个父类。

Python 2与3

这在Python 2和3中工作:

super(Child, self).__init__()

这只适用于Python 3:

super().__init__()

它通过在堆栈框架中移动并获得方法的第一个参数(通常self用于实例方法或cls类方法 - 但可以是其他名称)并Child在自由变量中找到类(例如,它在名称中__class__作为一个自由的关闭变量在方法中查找)。

我倾向于演示使用交叉兼容的方式super,但是如果您只使用Python 3,则可以不带参数地调用它。

具有向前兼容性的间接性

它给你什么?对于单一继承,从静态分析的角度来看,这个问题的例子实际上是相同的。但是,使用super向前兼容性给你一个间接层。

向前兼容对于经验丰富的开发人员非常重要。您希望自己的代码在更改时能够保持最小的更改。当你看你的修订历史,你想看看什么时候改变。

你可以从单一的继承开始,但是如果你决定添加另一个基类,你只需要改变这个基础 - 如果基类在你继承的类中改变(比如添加了一个mixin),你会改变这课没有什么 特别是在Python 2中,将参数取得超级以及正确的方法参数是很困难的。如果你知道你正在使用super单一的继承,这使得调试更困难的前进。

依赖注入

其他人可以使用你的代码,并将父母注入方法解析:

class SomeBaseClass(object):def __init__(self):print('SomeBaseClass.__init__(self) called')class UnsuperChild(SomeBaseClass):def __init__(self):print('UnsuperChild.__init__(self) called')SomeBaseClass.__init__(self)class SuperChild(SomeBaseClass):def __init__(self):print('SuperChild.__init__(self) called')super(SuperChild, self).__init__()

假设你添加了另一个类到你的对象,并且希望在Foo和Bar之间插入一个类(用于测试或其他原因):

class InjectMe(SomeBaseClass):def __init__(self):print('InjectMe.__init__(self) called')super(InjectMe, self).__init__()class UnsuperInjector(UnsuperChild, InjectMe): passclass SuperInjector(SuperChild, InjectMe): pass

使用un-super子程序将无法注入依赖项,因为您正在使用的子项对要调用的方法进行硬编码:

>>> o = UnsuperInjector()UnsuperChild.__init__(self) calledSomeBaseClass.__init__(self) called

但是,使用该子类的类super可以正确注入依赖关系:

>>> o2 = SuperInjector()SuperChild.__init__(self) calledInjectMe.__init__(self) calledSomeBaseClass.__init__(self) called

结论

始终用于super引用父类。

你打算引用下一个在线的父类,而不是专门看到孩子继承的父类。

不使用super可以给你的代码的用户带来不必要的限制。