本文为精简笔记
参考链接:https://www.cnblogs.com/chenhuabin/p/10058594.html
super 是一个类,实例化后得到的是一个代理的对象,而不是得到父类,并且我们使用这个对象来调用父类和兄弟类的方法。
原理
用法
super()
super(type , obj)
super(type_1 , type_2)
super(type, obj)
!!!!!!!!!!!!!!!!!!!!!极为重要!!!!!!!!!!!!!!!!!!!!
type:指出用继承顺序中的哪个元素。
obj(某个类的实例化对象):指出用哪个类的继承顺序
step1.根据_mro_(method resolution order方法解析顺序)机制理清类的继承顺序(注意: 不是输出顺序)。
step2.调用type对应的类在__mro__顺序中的下一个类的方法(该方法为super(type, obj).__init__中的init,或者super(type, obj).fun()的fun())。
realize step1:
class A(object):
pass
class B(object):
pass
class C(object):
pass
class D(A,B):
pass
class E(B, C):
pass
class F(D, E):
pass
print(F.__mro__)
输出元素顺序为:F->D->A->E->B->C->object
为何输出这样的顺序?
1.找入度为0的并且左侧优先的点。2.将该点拿出并将与之相连的箭头全部删除。3.所有点的拿出顺序就是继承顺序(不要忘了在结尾加上父类)。
当要生成F的继承顺序时,C3算法过程如下:首先将入度(指向该节点的箭头数量)为零的节点放入列表,并将F节点及与F节点有关的箭头从上图树中删除;继续找入度为0的节点,找到D和E,左侧优先,故而现将D放入列表,并从上图树中删除D,这是列表中就有了F、D。继续找入度为0的节点,有A和E满足,左侧优先,所以是A,将A从上图中取出放入列表,列表中顺序为F、D、E;接下来入度为0的节点只剩下E,取出E放入列表;只剩下B和C节点,且入度都为0,但左侧优先,二先将B放入列表,然后才是后才是C;不过别忘了,Python所有类都有一个共同的父类,那就是object类,所以,最好还会把object放入列表末尾。
realize step2
我们接着在上面的代码后接入下面的代码:
super(E , F()).fun() # 起始元素为E,F类继承元素顺序为:F->D->A->E->B->C->object,目标方法为fun(),输出结果:B.fun
super(D , F()).fun() # 输出结果:A.fun
super(F , F()).fun() # 输出结果:D.fun
super(B , F()).fun() # 输出结果:C.fun
super(B , E()).fun() # 输出结果:起始元素为E,E类继承元素顺序为:E->B->C->object,目标方法为fun(),C.fun
super(B , B()).fun() # 这是错误的,会报错
以及下面一段代码:
class A:
def fun(self):
print('A.fun')
class B(A):
def fun(self):
super(B , self).fun()
print('B.fun')
class C(A):
def fun(self):
super(C , self).fun()
print('C.fun')
class D(B , C):
def fun(self):
super(D , self).fun()
print('D.fun')
D().fun()
#输出为
#A.fun
#C.fun
#B.fun
#D.fun
D类的__mro__顺序是D->B->C->A,在D类中调用fun方法,然后在D类fun方法中遇到super(D , self).fun(),这个self指的是D类的实例化对象,所以用的是D类的__mro__顺序,而且指明位置是D后面也就是B类,所以继续调用B类的fun方法,遇到super(B , self).fun(),这时候需要注意,这里的self还是原来的D类实例(千万注意不是B类实例),所以还是用D类的__mro__顺序,那就继续调用下一个C类的fun方法,同理继续调用下一个父类,也就是A类的fun方法,执行完A类的fun方法后,回到C的fun方法中,打印输出,然后回到B类的fun方法,直到D类的fun方法打印输出完。