pyhon新式类多重继承的mro顺序确定: c3算法


本文写作目的:试图以最清晰简洁的方式介绍python新式类的C3算法

python经典类和新式类:
 python中的新式类是指直接或间接继承自object的类,而经典类则是没有直接或间接继承object的类,新式类和经典类的重要区别就是它们的MRO(方法解析顺序)不同,经典类的mro顺序是用深度优先+从左至右的方法确定的(这里的"从左至右"是指定义子类时,多个基类的书写顺序从左至右),而新式类的MRO顺序则是用C3算法确定的(2.3版本不是C3,之后都是C3)。在python3中只支持新式类,即所有类都直接或者简介继承自object类,并且,定义一个类时如果没有显示写出基类,则默认继承自object类;在python2(2.3及以上)中则有经典类和新式类两种方式,在python2中定义新式类必须显示写出继承object类。

新式类的C3算法:
 方法解析顺序MRO其实就是确定子类和祖先类之间的一个线性顺序,这个顺序表达了各个祖先类(包括父类)对于子类的重要性(优先级),当类对象调用某个方法时,解释器会根据MRO列表去挨个找,直到找到一个同名的方法然后调用之,所以理解python继承结构中各个类的优先顺序对于写代码是必须的,C3算法过程如下。
 假设子类C的N个直接父类是B1,B2,…,BN,记L[C]是C的线性化列表(MRO表),L[B1],L[B2],…,L[BN]是N个父类的线性化列表,F=[B1,…,BN]是由N个父类构成的单个列表,其中B1,…,BN是按照定义类C时的书写顺序从左至右的。则L[C]就是由N+1个列表生成的,具体就是用下面的递归合并算法:

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

其中的merge的输入是N+1个列表,按照如下方式输出一个长度为N的列表:

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

可能第一次看这个过程不是很能理解,举个栗子就很清晰啦。(图是偷来的,嘻嘻),需要注意一下,图中多个父类的左右顺序和继承顺序是一致的。
在这里插入图片描述
如上图的继承结构,现在要求类A的MRO列表,记O为object,假设已经求出各个祖先类的MRO表如下:

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

则L[A]的合并过程如下:

L[A] = A + merge([B,D,E,O],[C,D,F,O],[B,C]) # 取出B </
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值