Python多重继承顺序---C3算法

什么是多重继承C3算法

  • MRO即 method resolution order (方法解释顺序),主要用于在多继承时判断属性的路径(来自于哪个类)。
  • 在python2.2版本中,算法基本思想是根据每个祖先类的继承结构,编译出一张列表,包括搜索到的类,按策略删除重复的。但是,在维护单调性方面失败过(顺序保存)。C3是1996年首次被提出。在python2.3及后续版本中,C3被选定为默认的解析算法。C3线性表是用于获取多重继承下继承顺序的一种算法。
  • C3算法最早被提出是用于Lisp的,应用在Python中是为了解决原来基于深度优先搜索算法不满足本地优先级,和单调性的问题。

(本地优先级:指声明时父类的顺序,比如C(A,B),如果访问C类对象属性时,应该根据声明顺序,优先查找A类,然后再查找B类。
单调性:如果在C的解析顺序中,A排在B的前面,那么在C的所有子类里,也必须满足这个顺序。)

c3算法方法

一个类的C3线性表,是由两部分进行merge操作得到的,第一部分是是它所有父类的C3线性表(parents' linearizations),第二部分是它所有父类组成的列表(parents list)。后者其实是局部的优先级列表。

L(Child(Base1,Base2)) = [ Child + merge( L(Base1) ,  L(Base2) ,  Base1Base2 )]

L(object) = [ object ]

所谓merge操作,遵循以下原则:表的首个元素不可以出现在其他地方,如果出现了这样的情形,那么就要将该元素全部移出,放到产出列表(output list)中。如果循环进行这一操作,就可以把所有的表逐步移出,逐步扩张产出表,最后得到一个

纯粹的产出表。这个产出表就是最后的C3线性表。

merge: ①         如果列表空则结束,非空 读merge中第一个列表的表头,

               ②         查看该表头是否在 merge中所有列表的表尾中。

               ②-->③  不在,则 放入 最终的L中,并从merge中的所有列表中删除,然后 回到①中

               ②-->④  在,查看 当前列表是否是merge中的最后一个列表

               ④-->⑤  不是 ,跳过当前列表,读merge中下一个列表的表头,然后 回到 ②中

               ④-->⑥  是,异常。类定义失败。

表头: 列表的第一个元素 (列表:ABC,那么表头就是A,B和C就是表尾)

表尾: 列表中表头以外的元素集合(可以为空) 

merge 简单的说即寻找合法表头(也就是不在表尾中的表头),如果所有表中都未找到合法表头则异常。

C3算法的三大重要属性:

1.前趋图。作为有向无环图,找不到任何的循环,通常用前趋图来理解程序的依赖关系。

2.保持局部的优先次序。

3.单调性。 

举个例子:

L(D) = L(D(O))

     = D + merge(L(O))

     = D + O

     = [D,O]

L(B) = L(B(D,E))

     = B + merge(L(D) , L(E))

     = B + merge(DO , EO) # 第一个列表DO的表头D,其他列表比如EO的表尾都不含有D,所以可以将D提出来,即D是合法表头

     = B + D + merge(O , EO) #从第一个开始表头是O,但是后面的列表EO的表尾中含有O所以O是不合法的,所以跳到下一个列表EO

     = B + D + E + merge(O , O)

     = [B,D,E,O]

同理:

L(C) = [C,E,F,O]

L(A(B,C)) = A + merge(L(B),L(C),BC)

          = A + merge(BDEO,CEFO,BC)#B是合法表头

          = A + B + merge(DEO,CEFO,C)#D是合法表头

          = A + B + D + merge(EO,CEFO,C)#E不是合法表头,跳到下一个列表CEFO,此时C是合法表头

          = A + B + D + C + merge(EO,EFO)#由于第三个列表中的C被删除,为空,所以不存在第三个表,只剩下两个表;此时E是合法表头

          = A + B + D + C + E + merge(O,FO)#O不是合法表头,跳到下一个列表FO,F是合法表头,

          = A + B + D + C + E + F + merge(O,O)#O是合法表头

          = A + B + D + C + E + F + O

          = [A,B,D,C,E,F,O]

获取C3的数组列表,可以梳理清楚子类执行过程中向上执行的顺序

猜你喜欢

转载自blog.csdn.net/u010359398/article/details/81205206