Skip to content

Latest commit

 

History

History
79 lines (50 loc) · 3.38 KB

308.md

File metadata and controls

79 lines (50 loc) · 3.38 KB

#如何使用 ' 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有可能给你的代码用户带来不必要的限制。