Python中super的用法

【引用】https://www.cnblogs.com/chenhuabin/p/10058594.html
添加了个人的理解

1.MRO(Method Resolution Order):方法解析顺序

MRO其实就是以祖先类(包括父类)对于子类的重要性(优先级)来生成的一个序列。当类对象调用某个方法时,解释器会根据MRO列表去挨个找,直到找到一个同名的方法然后调用之。
目前Python3采用C3算法获得顺序。对于不同的类,它的mro不同。

C3算法:
1>将入度(指向该节点的箭头数量)为零的节点放入列表,左侧优先
2>将该节点及与该节点有关的箭头从上图树中删除
3>反复以上两个步骤,直到把所有节点都放入列表

以下图过一遍C3算法
在这里插入图片描述
F的mro顺序生成如下

步骤List
取F,删除F相关的箭头F
取D(左侧优先),删除D相关的箭头F→D
取A(A相对于E是左侧),删除A相关的箭头F→D→A
取E,删除E相关的箭头F→D→A→E
取B,删除B相关的箭头F→D→A→E→B
取C,删除C相关的箭头F→D→A→E→B→C

最后得到的顺序即:F->D->A->E->B->C->object.

同理可得:
E的mro顺序生成:E->B->C->object.
D的mro顺序生成:D->A->B->object.
A的mro顺序生成:A->object.
B的mro顺序生成:B->object.
C的mro顺序生成:C->object.

可用下面的代码运行观察:

class A(object):
    def fun(self):
        print('A.fun')

class B(object):
    def fun(self):
        print('B.fun')

class C(object):
    def fun(self):
        print('C.fun')

class D(A,B):
    def fun(self):
        print('D.fun')

class E(B, C):
    def fun(self):
        print('E.fun')

class F(D, E):
    def fun(self):
        print('F.fun')
        
print(F.__mro__)
print(E.__mro__)
print(D.__mro__)
print(A.__mro__)

2.super是用来引用父类的,可以完美的在多继承的情况下引用父类。

例1:

class A:
    def fun(self):
        print('A.fun')

class B(A):
    def fun(self):
        super(B , self).fun()
        print('B.fun')

最常用的形式:super(类名,self).init()
例2:

class  A(Parents):
    def __init__(self):
            super(A,self).__init__()
            print '引用父类的初始化'

3.super的三种调用方法

super().方法
super(type , obj).方法
super(type_1 , type_2).方法

注意:super 的第一个参数尽量为当前的类。

①super(type , obj).方法
第二个参数是type参数类的实例化对象,也可以是该类的子类的实例化对象。obj用于确定搜索的MRO。即:用obj的MRO序列进行搜索
第一个参数type必须是一个类名。对于MRO的搜索会从 type 之后的类开始。
例:用上面介绍MRO的图片例子

class A(object):
    def notFun(self): # A中没有fun函数
        print('A.notFun')

class B(object):
    def fun(self):
        print('B.fun')

class C(object):
    def fun(self):
        print('C.fun')

class D(A,B):
    def fun(self):
        print('D.fun')

class E(B, C):
    def fun(self):
        print('E.fun')

class F(D, E):
    def fun(self):
        print('F.fun')

super(B , F()).fun() # 输出结果:C.fun
super(D , F()).fun() # 输出结果:E.fun
super(E, E()).fun() # 输出结果:B.fun
super(A , A()).fun() # 报错

分析:
由1已知:
F的mro顺序生成:F->D->A->E->B->C->object.
E的mro顺序生成:E->B->C->object.
D的mro顺序生成:D->A->B->object.
A的mro顺序生成:A->object.
B的mro顺序生成:B->object.
C的mro顺序生成:C->object.
(1)super((B , F()).fun() 即用F的mro顺序,从B之后的类开始搜索。
即在C中搜索,有fun()函数,视为找到,不再进行后续搜索,并执行C中的fun()
(2)super(D , F()).fun() 即用F的mro顺序,从D之后的类开始搜索。
即在A中搜索,没有fun()函数,继续在E中找,有fun()函数,视为找到,不再进行后续搜索,并执行E中的fun()
(3)super(E , E()).fun() 即用E的mro顺序,从E之后的类开始搜索。
即在B中搜索,有fun()函数,视为找到,不再进行后续搜索,并执行B中的fun
(4)super(A , A()).fun()
A的父类是object,没有fun函数,搜索序列也结束了,所以报父类没有这个函数的错误

②super().方法
相当于super(当前类名 , self)。这种方式只能用在类体内部,不像上面的例子可以把super拿出来。
例:

class A:
    def fun(self):
        print('A.fun')

class B(A):
    def fun(self):
        super().fun()
        print('B.fun')

③ super(type_1 , type_2).方法
当super传入的两个参数都是类名是,type_2必须是type_1的子类。
例1:
super(B , E) 即 用E的mro顺序,取B之后的类的代理,即C的代理,并未对C进行实例化,所以不能调用C中的方法
例2:给例1加上实例,这一块我不是很懂,好像只要是声明了的class就可以,即便和继承树图完全没关系的类也可以,只要这个类声明了就行。
super(B , E).fun(A()) # 输出结果:C.fun
super(B , E).fun(ShiLi()) # 输出结果:C.fun,ShiLi类声明过

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值