Python MRO
考虑这个例子:
O = object
class F(O): pass
class E(O): pass
class D(O): pass
class C(D,F): pass
class B(D,E): pass
class A(B,C): pass
L[A] = A + merge(L[B], L[C], BC)
L[B] = B + merge(L[D],L[E],DE)
L[C] = C + merge(L[D],L[F], DF)
L[D]= D + merge(L[O])
L[E] = E + merge(L[O])
L[F] = F + merge(L[O])
L[O] = O
所以,L[D],L[E],L[F] 分别等于 DO,EO,FO
重新整理之后为:
L[A] = A + merge(L[B], L[C], BC)
L[B] = B + merge(DO,EO,DE)
L[C] = C + merge(DO, FO, DF)
L[D]= DO
L[E] = EO
L[F] = FO
L[O] = O
我在这里先去计算了L[D],L[E],L[F]是为了从开始考虑每个列表的head是否出现于其他列表的tail时,可以更直接的判断出结果,从而判断出该head是否为一个合法head,这样的思考顺序科学吗?
接下来我们应该先处理L[C]?
L[C]中,D是一个合法head,所以L[C] = CD + merge(O,FO,F)
接下来该考虑FO中的F了?
F仍然为一个合法head,因此L[C] = CDF + merge(O,O) ,此时因为处理merge(O,O)时 O仍然是合法head,所以L[C]=CDFO
接下来看L[B] = B + merge(DO,EO,DE)
D是合法head,因此L[B] = B + D + merge(O,EO,E)
E是合法head,因此L[B] = B + D + E + merge(O,O) = BDEO
最后看L[A] = A + merge(L[B], L[C], BC)
将刚才计算出来的L[B],L[C]结果带入
L[A] = A + merge(BDEO, CDFO, BC)
B是合法head,L[A] = A + B + merge(DEO, CDFO, C)
C是合法head,L[A] = A + B + C + merge(DEO, DFO)
D是合法head,L[A] = A + B + C + D + merge(EO, FO)
依次,E和F是合法head,所以L[A] = A + B + C + D + E + F + O
你认为这个逻辑科学吗?对吗?
你的推导是对的,而且思考顺序也“很科学”。👍
C3 线性化本来就要求先递归求出父类的线性化 L[Bi],然后再做一次 merge(L[B1], L[B2], …, [B1, B2, …])。你先算出 L[D], L[E], L[F] 再算 L[C]、L[B],最后合并到 L[A],完全符合算法。
逐步核对你给的步骤(关键检查点):
L[C] = C + merge(DO, FO, [D, F]):首元素D不出现在其它序列的 tail 中 ⇒ 取D;接着F合法 ⇒ 取F;最后两个O合并 ⇒L[C]=CDFO✅L[B] = B + merge(DO, EO, [D, E]):先取D,再取E,最后两个O⇒L[B]=BDEO✅L[A] = A + merge(BDEO, CDFO, [B, C]):依次取B、C、D、E、F,最后O⇒L[A]=ABCDEFO✅
两点小提示(更严谨/通用的写法):
- 严格的公式里,单继承也要把“父类列表本身”并进去:例如
L[D] = [D] + merge(L[O], [O]),这一步最后当然还是DO,你直接写成DO是简写没问题。 - 判断“合法 head”时,只需要看其它序列的 tail,不看它们的 head。这一点你在推导中做得对。
你也可以用 Python 验证一下(会得到同样的顺序):
O = object
class F(O): pass
class E(O): pass
class D(O): pass
class C(D, F): pass
class B(D, E): pass
class A(B, C): pass
print([cls.__name__ for cls in A.mro()])
# ['A', 'B', 'C', 'D', 'E', 'F', 'object']
结论:你的思路与结果都正确;L[A] = A B C D E F O 就是这个层次结构的 MRO。
本文来自博客园,作者:ijpq,转载请注明原文链接:https://www.cnblogs.com/ijpq/p/19138173

浙公网安备 33010602011771号