C3线性化

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

MRO

MRO 全称方法解析顺序(Method Resolution Order),它决定基类中的函数到底应该以什么样的顺序调用父类中的函数。

大体顺序如下:

for(遍历执行merge操作的序列){
    if(一个序列的第一个元素在其他序列中也是第一个元素 || 不在其他序列出现){
        从所有执行merge操作序列中删除这个元素
        合并到当前的mro中
    }

    if(merge操作的序列为空){
        done;
    }

    if(最后一次merge操作完成 && merge操作的序列无法为空){
        throw;
        该继承不合法
    }

}

示例:

class A(O)
class B(O)
class C(O)
class E(A,B)
class F(B,C)
class G(E,F)

意思是:A 继承O,B继承O,C继承O;E继承A和B,F继承B和C,G继承E和F。

分析E:

[E] = [E] + merge([A], [B], [A,B])
= [E] + merge([A,O], [B,O], [A,B])

因为 A是序列[A,O]中的第一个元素,而且在序列[B,O]中不出现,而且在序列[A,B]中也是第一个元素,所以删除A、合并到E,得:

[E] = [E,A] + merge([O], [B,O], [B])

继续分析:

  • O是序列[O]中的第一个元素,但O在序列[B,O]中出现并且不是其中第一个元素,因此不能合并

  • B是[B,O]的第一个元素,所以删除B,合并到E,得:

  • [E] = [E,A,B] + merge([O], [O])
    

两个[O] 可以直接合并了,因此最终结果是 : [E,A,B,O]

推导F也是一样的道理,在这里建议读者不妨先自己推理一遍,然后再对照答案。

(F) = [F] + merge([B], [C], [B,C])
= [F] + merge([B,O], [C,O], [B,C])
= [F,B] + merge([O], [C,O], [C])
= [F,B,C] + merge([O], [O])
= [F,B,C,O]

results matching ""

    No results matching ""