python mro c3_Python3中的C3算法:多继承查找规则

Python3中的C3算法:多继承查找规则

Python3探索

一、基本概念

1. mro序列

MRO是一个有序列表L,在类被创建时就计算出来。如果继承至一个基类:class B(A)

这时B的mro序列为

mro( B ) = mro( B(A) )

= [B,A]

如果继承至多个基类:class B(A1,A2,A3 ...)

这时B的mro序列

mro(B) = mro( B(A1,A2,A3 …) )

= [B] + merge(mro(A1), mro(A2), mro(A3) ..., [A1,A2,A3])

计算结果为列表,列表中至少有一个元素即类自己,如上述示例[A1,A2,A3]。merge操作是C3算法的核心。

2. 表头和表尾:表尾:

列表中表头以外的元素集合(可以为空)

表头:

列表的第一个元素

示例

列表:[A, B, C]

表头是A,表尾是B和C

3. merge操作:

merge操作流程图:

Created with Raphaël 2.1.2Start① 判断merge列表是否为空?>>是空。如果列表为空,本次merge操作结束,如有下次计算则继续>>不是空。如果列表非空,读取merge中第一个列表的表头继续判断下一步② 查看该表头是否在merge中的所有列表的表尾中?>>不在,则将该表头放入最终的L中(外层)并从merge中的所有列表中删除,然后回到①中>>在,继续判断下一步③ 查看当前列表是否是merge中的最后一个列表?>>不是,跳过当前列表,回到①中查找下一个列表>>是,异常。类定义失败。End回到①yesnoyesnoyesno

二、实例

1. 计算实例1

示例:(多继承UML图,引用见参考)

备注:O==object

如何计算mro(A) ?mro(A) = mro( A(B,C) )

原式= [A] + merge( mro(B),mro(C),[B,C] )

mro(B) = mro( B(D,E) )

= [B] + merge( mro(D), mro(E), [D,E] )

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

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

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

= [B,D,E,O]

mro(C) = mro( C(E,F) )

= [C] + merge( mro(E), mro(F), [E,F] )

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

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

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

= [C,E,F,O]

原式= [A] + merge( [B,D,E,O], [C,E,F,O], [B,C])

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

= [A,B,D] + merge( [E,O], [C,E,F,O], [C]) # 此步为重点,跳过E

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

= [A,B,D,C,E] + merge([O], [F,O]) # 跳过O

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

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

2. 代码测试

对于以上计算,用代码来测试。

classD:pass

classE:pass

classF:pass

classB(D,E):pass

classC(E,F):pass

classA(B,C):pass

print("从A开始查找:")

forsinA.__mro__:

print(s)

print("从B开始查找:")

forsinB.__mro__:

print(s)

print("从C开始查找:")

forsinC.__mro__:

print(s)

结果:从A开始查找:

从B开始查找:

从C开始查找:

三、总结

每次判断如何读取都要这么麻烦计算吗?可有简单方法?

我对此做了一个简单总结。

1. 规律总结

如何快速判断查找规律?从 “当前子类” 向上查找它的父类,

若 “当前子类” 不是 “查找的父类” 的最后一个继承的子类时,则跳过该 “查找的父类” 的查找,开始查找 “当前子类” 的下一个父类

查找规律流程图:

Created with Raphaël 2.1.2Start① 从 “当前子类” 向上查找它的父类② 判断该父类属性。当前父类是否还有后续其他子类?若是。则跳过当前父类。对当前子类, 开始查找下一个父类若没有后续子类。则将该父类记录进入__mro__列表———End一次查找结束yesno

2. 规律测试

实例2:

对于如下继承:

通过如下判断模式:

代码测试:

classA1:pass

classA2:pass

classA3:pass

classB1(A1,A2):pass

classB2(A2):pass

classB3(A2,A3):pass

classC1(B1):pass

classC2(B1,B2):pass

classC3(B2,B3):pass

classD(C1,C2,C3):pass

print("从D开始查找:")

forsinD.__mro__:

print(s)

print("从C3开始查找:")

forsinC3.__mro__:

print(s)

结果预测:

四、参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值