关于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使用的算法是广度优先原则。

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

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

猜你喜欢

转载自www.cnblogs.com/LegendsNeverDie/p/10360560.html