python新式类继承------C3算法

一、引入

mro即method resolution order,主要用于在多继承时判断调的属性的路径(来自于哪个类)。之前查看了很多资料,说mro是基于深度优先搜索算法的。但不完全正确在Python2.3之前是基于此算法,但从Python2.3起应用了新算法:C3算法。

二、为什么采用C3算法

C3算法最早被提出是用于Lisp的,应用在Python中是为了解决原来基于深度优先搜索算法不满足本地优先级,和单调性的问题。
本地优先级:指声明时父类的顺序,比如C(A,B),如果访问C类对象属性时,应该根据声明顺序,优先查找A类,然后再查找B类。
单调性:如果在C的解析顺序中,A排在B的前面,那么在C的所有子类里,也必须满足这个顺序。

三、C3算法的实现

1.多继承UML图:

                                           

2.python-C3算法解析:

判断mro要先确定一个线性序列,然后查找路径由由序列中类的顺序决定。所以C3算法就是生成一个线性序列。
如果继承至一个基类:
class B(A)
这时B的mro序列为[B,A]
 
如果继承至多个基类
class B(A1,A2,A3 ...)
这时B的mro序列 mro(B) = [B] + merge(mro(A1), mro(A2), mro(A3) ..., [A1,A2,A3])
 

C3算法的本质就是Merge,不断地把mro()函数返回的序列进行Merge,规则如下:

1. 如果第一个序列的第一个元素,是后续序列的第一个元素,或者不再后续序列中再次出现,则将这个元素合并到最终的方法解析顺序序列中,并从当前操作的全部序列中删除。

2. 如果不符合,则跳过此元素,查找下一个列表的第一个元素,重复1的判断规则

merge: ① 如果列表空则结束,非空 读merge中第一个列表的表头,
               ② 查看该表头是否在 merge中所有列表的表尾中。
               ②-->③ 不在,则 放入 最终的L中,并从merge中的所有列表中删除,然后 回到①中
               ②-->④ 在,查看 当前列表是否是merge中的最后一个列表
               ④-->⑤ 不是 ,跳过当前列表,读merge中下一个列表的表头,然后 回到 ②中
               ④-->⑥ 是,异常。类定义失败。 
表头: 列表的第一个元素 (列表:ABC,那么表头就是A,B和C就是表尾)
表尾: 列表中表头以外的元素集合(可以为空) 
merge 简单的说即寻找合法表头(也就是不在表尾中的表头),如果所有表中都未找到合法表头则异常。

例如:

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]

原文地址:https://www.cnblogs.com/fengchong/p/10079698.html