super的实例及实现原理

super实例

class A():
    def go(self):
        print ("go A go!")
    def stop(self):
        print ("stop A stop!")
    def pause(self):
        raise Exception("Not Implemented")
class B(A):
    def go(self):
        super(B, self).go()
        print ("go B go!")
class C(A):
    def go(self):
        super(C, self).go()
        print ("go C go!")
    def stop(self):
        super(C, self).stop()
        print ("stop C stop!")
class D(B,C):
    def go(self):
        super(D, self).go()
        print ("go D go!")
    def stop(self):
        super(D, self).stop()
        print ("stop D stop!")
    def pause(self):
        print ("wait D wait!")
class E(B,C):
    pass
a = A()
b = B()
c = C()
d = D()
e = E()
# 说明下列代码的输出结果
a.go()
print('--------')
b.go()
print('--------')
c.go()
print('--------')
d.go()
print('--------')
e.go()
print('--------')
a.stop()
print('--------')
b.stop()
print('--------')
c.stop()
print('--------')
d.stop()
print('--------')
e.stop()
print(D.mro())
a.pause()
b.pause()
c.pause()
d.pause()
e.pause()

答案

a.go()# go A go!
b.go()# go A go!# go B go!
c.go()# go A go!# go C go!
d.go()# go A go!# go C go!# go B go!# go D go!
e.go()# go A go!# go C go!# go B go!
a.stop()# stop A stop!
b.stop()# stop A stop!
c.stop()# stop A stop!# stop C stop!
d.stop()# stop A stop!# stop C stop!# stop D stop!
e.stop()# stop A stop!
a.pause()# ... Exception: Not Implemented
b.pause()# ... Exception: Not Implemented
c.pause()# ... Exception: Not Implemented
d.pause()# wait D wait!
e.pause()# ...Exception: Not Implemented

  

super原理

super的工作原理如下:

def super(cls, inst):
    mro = inst.__class__.mro()
    return mro[mro.index(cls) + 1]

cls代表类,inst代表实例,可以看出上面的代码做了两件事:

  • 获取inst的MRO列表。
  • 查找cls在MRO的index,并返回它的下一个类,即mro[index + 1]

当你使用super(cls, inst)时,python会在inst的MRO列表上搜索下cls的下一个类。

现在再回答前面的例子:

super(C, self).__init__()

这里的self是C的实例,self.class.mro()的结果是;

[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>]

可以看到C的下一个类是A,于是,跳到了A的init,这时会打印enter A,并且执行下面一行代码:

super(A, self).__init__()

注意这里的self也是当前C的实例,MRO列表和之前是一样的。搜索A在MRO中下的一个类,发现是B,于是又跳到了B的init,这时会打印enter B,而不是enter Base。

上面整个过程还是比较清晰的,关键在于理解super的工作方式,而不是想当然的理解为super调用父类的方法。

总结:

  • super和父类没有实质性的关联。
  • super(cls, inst)获得的是cls在inst的MRO列表中下一个类。
原文地址:https://www.cnblogs.com/lice-blog/p/11581741.html