首页 > 编程语言 > 详细

Python的MRO以及C3线性化算法

时间:2019-05-25 17:11:26      阅读:149      评论:0      收藏:0      [点我收藏+]

python3?中的方法解析顺序 (Method Resolution Order , MRO)采用C3线性化算法来确定

(百度Python MRO排在首位的文章,绝大部分内容是正确的,但是核心公式错了)

简而言之,一个类的MRO应当如下确定

L[object] = [object]
L[C(B1…BN)] = [C] + merge(L[B1]…L[BN], [B1, … ,BN])

这里的关键在于?merge,其输入是一组列表,按照如下方式输出一个列表:

  1. 检查第一个列表的头元素(如?L[B1]?的头),记作?H。
  2. 若?H?未出现在其它列表的尾部,则将其输出,并将其从所有列表中删除,然后回到步骤1;否则,取出下一个列表的头部记作?H,继续该步骤。
  3. 重复上述步骤,直至列表为空或者不能再找出可以输出的元素。如果是前一种情况,则算法结束;如果是后一种情况,说明无法构建继承关系,Python 会抛出异常。

示例1

继承关系如下图
技术分享图片

根据上述C3算法的步骤来计算其MRO

首先计算B1的MRO:
L[B1(A1,A2)] = [B1] + merge(L[A1], L(A2), [A1, A2])
?? ??? ??? ? = [B1] + merge([A1,Obj], [A2,Obj], [A1,A2])
?? ??? ??? ? = [B1, A1] + merge([Obj], [A2,Obj], [A2])
?? ??? ??? ? = [B1, A1, A2] + merge([Obj], [Obj])
?? ??? ??? ? = [B1, A1, A2, Obj]

同理,计算B2的MRO(过程略):
L[B2(A3)] = [B2, A3, Obj]

最终计算并得到C的MRO
L[C(B1,B2)] = [C] + merge(L[B1(A1,A2)], L[B2(A3)], [B1,B2])
?? ??? ??? ?= [C] + merge([B1, A1, A2, Obj], [B2, A3, Obj], [B1,B2])
?? ??? ??? ?= [C, B1] + merge([A1, A2, Obj], [B2, A3, Obj], [B2])
?? ??? ??? ?= [C, B1, A1] + merge([A2, Obj], [B2, A3, Obj], [B2])
?? ??? ??? ?= [C, B1, A1, A2] + merge([Obj], [B2, A3, Obj], [B2])
?? ??? ??? ?= [C, B1, A1, A2, B2] +merge([Obj], [A3, Obj])
?? ??? ??? ?= [C, B1, A1, A2, B2, A3] +merge([Obj], [Obj])
?? ??? ??? ?= [C, B1, A1, A2, B2, A3, Obj]

根据C3算法成功构建了MRO,所以这个类的继承关系是被允许的,而且根据MRO可以明确地指出应当如何去查找其父类的属性/方法。即按照MRO列表由前向后的顺序来查找。

当然,我们完全没有必要去计算这个序列,直接使用.mro()类方法即可查看该类的MRO

C.mro()
[<class '__main__.C'>, <class '__main__.B1'>, <class '__main__.A1'>, <class '__main__.A2'>, <class '__main__.B2'>, <class '__main__.A3'>, <class 'object'>]

与我们计算的结果是相同的。

正确理解MRO是使用多重继承和super()完成多继承类协作任务的基础。

参考链接
Python的方法解析顺序(MRO)[转]

Python的MRO以及C3线性化算法

原文:https://www.cnblogs.com/miyauchi-renge/p/10922092.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!