mro python_python中的MRO算法[转]

为解决 Python 2.2 中 MRO 所存在的问题,Python 2.3以后采用了 C3 方法来确定方法解析顺序。你如果在 Python 2.3 以后版本里输入上述代码,就会产生一个异常,禁止创建具有二义性的继承关系:

>>> class C(A, B): pass

Traceback (most recent call last):

File "", line 1, in

class C(A, B): pass

TypeError: Error when calling the metaclass bases

Cannot create a consistent method resolution

order (MRO) for bases X, Y

我们把类 C 的线性化(MRO)记为 L[C] = [C1, C2,…,CN]。其中 C1 称为 L[C] 的头,其余元素 [C2,…,CN] 称为尾。如果一个类 C 继承自基类 B1、B2、……、BN,那么我们可以根据以下两步计算出 L[C]:`

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 会抛出异常。

该方法有点类似于图的拓扑排序,但它同时还考虑了基类的出现顺序。我们用 C3 分析一下刚才的例子。

object,X,Y 的线性化结果比较简单:

L[object] = [object]

L[X] = [X, object]

L[Y] = [Y, object]

A 的线性化计算如下:

L[A] = [A] + merge(L[X], L[Y], [X], [Y])

= [A] + merge([X, object], [Y, object], [X], [Y])

= [A, X] + merge([object], [Y, object], [Y])

= [A, X, Y] + merge([object], [object])

= [A, X, Y, object]

到了最后一步我们没有办法继续计算下去 了:X 虽然是第一个列表的头,但是它出现在了第二个列表的尾部;Y 虽然是第二个列表的头,但是它出现在了第一个列表的尾部。因此,我们无法构建一个没有二义性的继承关系,只能手工去解决(比如改变 B 基类中 X、Y 的顺序)。

我们再看一个没有冲突的例子:

计算过程如下:

L[object] = [object]

L[D] = [D, object]

L[E] = [E, object]

L[F] = [F, object]

L[B] = [B, D, E, object]

L[C] = [C, D, F, object]

L[A] = [A] + merge(L[B], L[C], [B], [C])

= [A] + merge([B, D, E, object], [C, D, F, object], [B], [C])

= [A, B] + merge([D, E, object], [C, D, F, object], [C])

= [A, B, C] + merge([D, E, object], [D, F, object])

= [A, B, C, D] + merge([E, object], [F, object])

= [A, B, C, D, E] + merge([object], [F, object])

= [A, B, C, D, E, F] + merge([object], [object])

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

当然,可以用代码验证类的 MRO,上面的例子可以写作:

>>> class D(object): pass

>>> class E(object): pass

>>> class F(object): pass

>>> class B(D, E): pass

>>> class C(D, F): pass

>>> class A(B, C): pass

>>> A.__mro__

(, , ,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值