super()入门级用法还是比较简单的.
在类的继承当中,如果要在子类中重写某个父类同名方法,该方法会覆盖父类的同名方法;但是,有的时候,我们在重写父类方法时,同时也要调用父类同名方法功能.这时,
我们可以通过使用super()方法来实现.比如:
1 class Father: 2 def __init__(self): 3 print("Father.__init__") 4 5 6 class Son(Father): 7 def __init__(self): 8 Father.__init__(self) ##这种方法不推荐使用 9 super(Son, self).__init__() ##主流用法 10 super().__init__() ##python3 支持这个写法 11 print("Son.__init__") 12 13 14 s = Son() 15 16 结果: 17 Father.__init__ 18 Father.__init__ 19 Father.__init__ 20 Son.__init__
在上面,Father是父类,Son是子类,我们在Son中重定义了__init__()函数,但同时也想执行父类[Father]类的__init__方法,我们使用了super(),
super()有三种方法.主流方法是第二种...
深入了解super()
从上面的例子的示范,可能觉得super()的使用很简单,无非就是在重写父类的同时,调用父类的方法..其实,在上面的例子中,super()获得的类刚好是父类,
在其他的一些情况下就不一定了,super其实和父类没有任何实质性的联系.
一个复杂的例子,涉及到python 类的多重继承,我使用的是python3.
1 class Base: 2 def __init__(self): 3 print("enter Base") 4 print("leave Base") 5 6 7 class A(Base): 8 def __init__(self): 9 print("enter A") 10 super().__init__() 11 print("leave A") 12 13 14 class B(Base): 15 def __init__(self): 16 print("enter B") 17 super().__init__() 18 print("leave B") 19 20 21 class C(A, B): 22 def __init__(self): 23 print("enter C") 24 super().__init__() 25 print("enter C") 26 27 28 c = C()
其中,Base是父类,A,B继承自Base,C继承A,B,继承关系图
Base / / A B / / C
代码执行结果:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 enter C 2 enter A 3 enter B 4 enter Base 5 leave Base 6 leave B 7 leave A 8 enter C
看了结果,是不是和你想的有点不一样?你想的是不是,enter A的下一句enter Base?
这里的结果和我们所认为的有所差别.原因在于,super和父类是没有实质性的联系.下面让我们看看,super在程序中道理是如何运行的!
MRO列表
python的类继承,在我们每定义一个类,都会计算出一个方法解析顺序(Method Reselution Order,MRO)列表.我们可以使用下面的方式获得一个类的MRO列表.
print(C.mro()) [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>]
一个类的 MRO 列表就是合并所有父类的 MRO 列表,并遵循以下三条原则:
- 子类永远在父类前面
- 如果有多个父类,会根据它们在列表中的顺序被检查
- 如果对下一个类存在两个合法的选择,选择第一个父类
super原理
接上面代码后面
1 def super(cls, inst): 2 """ 3 1.获取inst的MRO列表 4 2.查找cls在当前MRO列表中的index,并返回它的下一个类,即mro[index + 1] 5 总结:当你使用 super(cls, inst) 时,Python 会在 inst 的 MRO 列表上搜索 cls 的下一个类。 6 :param cls: 代表类 7 :param inst: 代表实例 8 :return: 9 """ 10 mro = inst.__class__.mro() 11 return mro[mro.index(cls) + 1] 12 ret = super(C,c) 13 print(ret) 14 结果:<class '__main__.A'>
好了,让我们回到之前的例子:
super(C,self).__init()
这里的self是当前C的实例,self.class.mro()结果:
1 [__main__.C, __main__.A, __main__.B, __main__.Base, object]
可以看出,C的下一个类是A,于是,跳到了A的__init__.这是会打印enter A,执行下一句
super(A,self).__init__()
注意,这里的 self 也是当前 C 的实例,MRO 列表跟上面是一样的,搜索 A 在 MRO 中的下一个类,发现是 B,于是,跳到了 B 的 __init__
,这时会打印出 enter B,而不是 enter Base。
=.=