zoukankan      html  css  js  c++  java
  • 关于Python类的多继承中的__mro__属性使用的C3算法以及继承顺序解释

    刚刚学到类的多继承这个环节,当子类继承多个父类时,调用的父类中的方法具体是哪一个我们无从得知,为此,在Python中有函数__mro__来表示方法解析顺序。

    当前Python3.x的类多重继承算法用的是C3

    MRO序列:

    MRO是一个有序列表L,在类被创建时就计算出来。
    通用计算公式为:mro(Child(Base1,Base2)) = [ Child ] + merge( mro(Base1), mro(Base2), [ Base1, Base2] )其中Child继承自Base1, Base2)如果类B继承类A:

    这时类B的mro序列为:

    mro( B ) = mro( B(A) )
    = [B] + merge( mro(A) + [A] )
    = [B] + merge( [A] + [A] )
    = [B,A]
    

    如果继承至多个基类:class B(A1, A2, A3 …)
    这时B的mro序列为:

    mro(B) = mro( B(A1, A2, A3 …) )
    = [B] + merge( mro(A1), mro(A2), mro(A3) ..., [A1, A2, A3] )
    = ...

    计算得到的结果为列表,列表中第一个元素为自身,如上述示例[A1,A2,A3],merge操作是C3算法的核心,了解了merge操作的原理,就了解了C3算法。

    merge操作:

    假如计算merge( [E,O], [C,E,F,O], [C] )

    取出第一个列表[E,O]的表头E,进行判断:
    各个列表的表尾分别是[O], [E,F,O],E在这些表尾的集合中,因而跳过当前当前列表
    取出第二个列表[C,E,F,O]的表头C,进行判断:
    C不在各个列表的集合中,因而将C拿出到merge外,并从所有表头删除
    merge( [E,O], [C,E,F,O], [C]) = [C] + merge( [E,O], [E,F,O] )
      ...

    假设有如下的继承关系

    计算mro(A)的方式为:

    mro(A) = mro( A(B,C) )
    
    原式= [A] + merge( mro(B),mro(C),[B,C] )
    
      mro(B) = mro( B(D,E) )
             = [B] + merge( mro(D), mro(E), [D,E] )  # 多继承
             = [B] + merge( [D,O] , [E,O] , [D,E] )  # 单继承mro(D(O))=[D,O]
             = [B,D] + merge( [O] , [E,O]  ,  [E] )  # 拿出并删除D
             = [B,D,E] + merge([O] ,  [O])
             = [B,D,E,O]
    
      mro(C) = mro( C(E,F) )
             = [C] + merge( mro(E), mro(F), [E,F] )
             = [C] + merge( [E,O] , [F,O] , [E,F] )
             = [C,E] + merge( [O] , [F,O]  ,  [F] )  # 跳过O,拿出并删除
             = [C,E,F] + merge([O] ,  [O])
             = [C,E,F,O]
    
    原式= [A] + merge( [B,D,E,O], [C,E,F,O], [B,C])
        = [A,B] + merge( [D,E,O], [C,E,F,O],   [C])
        = [A,B,D] + merge( [E,O], [C,E,F,O],   [C])  # 跳过E
        = [A,B,D,C] + merge([E,O],  [E,F,O])
        = [A,B,D,C,E] + merge([O],    [F,O])  # 跳过O #注意O即为所有类的基类object
        = [A,B,D,C,E,F] + merge([O],    [O])
        = [A,B,D,C,E,F,O]

     根据上图的继承关系:

    可以得到A的mro序列为:[A,B,D,C,E,F,O]

    这里备注一下新式类和旧式类的区别:

    Python2.X中有新式类和旧式类之分:

    在Python2.X中,新式类需要特别定义为如下形式:

    class Tencent(object):

     旧式类:

    class Tencent()
    #或者
    class Tencednt:   #两种定义方式均为旧式类。
    

    而在Python3.X中,所有类无论以哪种方式定义,均为形式类。

    class Tencent():  #新式类
    class Tencent:     #新式类
    class Tencent(object):  #还是新式类

    在Python2.X中mro使用的算法是深度优先原则。

     深度优先即从左往右依次先向上搜索,然后再按从左至右的顺序搜索。

    在Python3.X中mro使用的算法是广度优先原则。

    广度优先即先满足从左至右搜索的原则,然后在向上搜索。

    以上就是相关解释,其中包含个人的想法,特此记录下来以免日后忘记,若有错误之处,望指正,感谢。

  • 相关阅读:
    sysctl.conf文件详解
    EOF的用法
    centos7下mail邮件的查看删除、禁止部分应用发邮件
    change命令
    mac访达显示路径复制路径
    MacOS修改默认的python版本和pip版本
    mac自带录屏
    excel
列A
去除列B后的数据
    selenium初识:selenium的安装及简单实现百度搜索
    React如何运行从github上下载的代码
  • 原文地址:https://www.cnblogs.com/LegendsNeverDie/p/10360560.html
Copyright © 2011-2022 走看看