#如何使用 ' super '
原问题地址:http://stackoverflow.com/questions/222877/how-to-use-super-in-python
##问题:
有人能给我解释下面两组代码的区别吗?
class Child(SomeBaseClass):
def __init__(self):
super(Child, self).__init__()
和这个:
class Child(SomeBaseClass):
def __init__(self):
SomeBaseClass.__init__(self)
我在类里面看到过很多关于super的应用,这些类都只有单一继承。我能明白为什么你会在多重继承中使用它,但我不清楚在这种情况下使用它有什么优势。
##回答 1:
在单一继承中使用super()
的好处微乎其微。主要的好处是:你不需要把基类的名称硬编码到每一个使用父类方法的方法中。
然而,使用不带有super()
的多重继承几乎是不可能的。包括常见的如混入类【译者注:关于mixin(混入类),推荐阅读:设计模式 Mixin (混入类)】、接口、抽象类,等等。这样的拓展了你编码。如果有人将来想创建一个类,让这个类从子类扩展到混入类,他们的代码将无法正常运行。
##回答 2:
###间接的向前兼容性
super的应用给你带来了什么?对于单一继承,上述内容实际上是从静态分析的角度来看问题的。然而,super使你的代码具有间接的向前兼容性。
向前兼容性对经验丰富的开发人员非常重要。你希望在你对代码做出修改后,能够以最低限度的代价继续工作。当你查看修订记录时,你想精确地看到修改的时间和内容。
你可以从单一继承开始,但是如果你决定添加另一个基类,你只需要改变基类那行。特别是在Python 2中,恰当地获取super的参数和正确的方法参数是很困难的。如果你知道你在正确使用带有单一继承的super,调试的进展就不那么困难。
###依赖注入
其他人可以使用你的代码,并向你的方法解析中注入父类方法:
class SomeBaseClass(object):
def __init__(self):
print('SomeBaseClass.__init__(self) called')
class Child(SomeBaseClass):
def __init__(self):
print('Child.__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(Child, InjectMe): pass
class SuperInjector(SuperChild, InjectMe): pass
使用不带有super的子类没能成功地注入依赖,因为你试图通过硬编码方法调用正在使用的子类本身:
>>> o = UnsuperInjector()
Child.__init__(self) called
SomeBaseClass.__init__(self) called
然而,如果你的类所包含的子类使用了super,这个类就可以正确地注入依赖:
>>> o2 = SuperInjector()
SuperChild.__init__(self) called
InjectMe.__init__(self) called
SomeBaseClass.__init__(self) called
不使用super有可能给你的代码用户带来不必要的限制。