简而言之,因为 C 依赖于 E,正如您在依赖图中看到的那样(O 是 object):
Python 的 方法解析顺序 (MRO) 的约束条件是,如果类 a 是类 b 的依赖项,则它是比 b 排在队列后面。
现在更多的是理论:
在 Python 中,MRO 使用以下 线性化 规则:
L[C(B1 ... Bn)] = C + merge(L[B1] ... L[Bn], B1 ... Bn);和
L[object] = object
(source)
而merge定义为:
取第一个列表的头部,即L[B1][0];如果这个头部不在任何其他列表的尾部,则将其添加到 C 的线性化中并从合并中的列表中删除,否则查看下一个列表的头部并取它,如果它是好头。然后重复这个操作,直到所有的类都被移除或者不可能找到好的磁头。在这种情况下,无法构造合并,Python 2.3 将拒绝创建 C 类并引发异常。
(source)
所以对于你的情况,第一步是:
L[A] = A + 合并(L[D],L[B],L[E])
让我们首先解决递归调用:
L[D] = D + merge(L[E],L[F]);
L[B] = B + 合并(L[C],L[H]);和
L[E] = E + merge(L[G],L[H])。
还有更多的递归(我们只做一次H,不重做E):
L[F] = F + merge(L[O]);
L[C] = C + merge( L[E],L[G]);
L[G] = G + merge(L[O]);和
L[H] = H + merge(L[O])。
由于 L[O] 是 O 和 merge(a)(对于一个对象是 a)我们因此有已经获得H、G和F的序列:
L[H] = (H, O)。
L[G] = (G, O).
L[F] = (F, O).
现在我们可以计算L[E]:
L[E] = E + 合并( (G,O) , (H,O) )。
由于O 都在尾部,所以放在最后:
L[E] = (E,G,H,O)。
现在我们可以计算L[C]:
L[C] = C + 合并( (E,G,H,O) , (G,O) );
L[C] = (C,E) + 合并( (G,H,O) , (G,O) );
L[C] = (C,E,G) + 合并( (H,O) , (O) );
L[C] = (C,E,G,H) + 合并( (O) , (O) );
*L[C] = (C,E,G,H,O)。
还有L[D]:
L[D] = D + 合并( (E,G,H,O) , (F,O) );
..;
L[D] = (D,E,G,H,F,O)。
接下来L[B]就可以完全解决了:
L[B] = B + 合并( (C,E,G,H,O) , (H,O) );
..;
L[B] = (B,C,E,G,H,O)。
现在我们终于可以解决了:
L[A] = A + 合并( (D,E,G,H,F,O) , (B, C,E,G,H,O) , (E,G,H,O) );
L[A] = (A,D) + 合并( (E,G,H,F,O) , (B,@987654 E,G,H,O) , (E,G,H,O) );
L[@987654502 @] = (A,D,B) + 合并( (E,G,H,F,O) , (C,@987654 G,H,O) , (E,G,H,O) );
L[A] = ( A,D,B,C) + 合并( (E,G,H,F,O) , (G,E, H,O) , (E,G,@987654 536@,O) );
L[A] = (A,D,B,C,E) + 合并( (G,H,F,O) , (G,H,O) , (G,H,O) ;
L[A] = (A,D,B,C,E,G) + 合并( (H,F ,O) , (H,O) , (H,O) );
L[A] = (A,@ 987654570@,B,C,E,G,H) + 合并( (F,O) , (O) , (@98765457) em>;
L[A] = (A,D,B,C,E,G,H,F) +合并( (O) , (O) , (O) );
L[A] = (A,D,B ,C,E,G,H,F,O).
这是预期的行为。
我制作的一个效率不高的合并功能可以用于教育目的,它绝对没有针对生产进行优化:
def mro_merge(*args):
for i,arg in enumerate(args):
if len(arg) > 0:
head = arg[0]
for argb in args:
if head in argb[1:]:
break
else:
newargs = tuple(argb if len(argb) > 0 and argb[0] != head else argb[1:] for argb in args)
print('mro_merge(%s) = %s + mro_merge(%s)'%(args,head,newargs))
yield head
for x in mro_merge(*newargs):
yield x
break
当你调用它时,它会生成:
>>> list(mro_merge(('G','O'),('H','O')))
mro_merge((('G', 'O'), ('H', 'O'))) = G + mro_merge((('O',), ('H', 'O')))
mro_merge((('O',), ('H', 'O'))) = H + mro_merge((('O',), ('O',)))
mro_merge((('O',), ('O',))) = O + mro_merge(((), ()))
['G', 'H', 'O']
>>> list(mro_merge( ('D','E','G','H','F','O') , ('B','C','E','G','H','O') , ('E','G','H','O') ))
mro_merge((('D', 'E', 'G', 'H', 'F', 'O'), ('B', 'C', 'E', 'G', 'H', 'O'), ('E', 'G', 'H', 'O'))) = D + mro_merge((('E', 'G', 'H', 'F', 'O'), ('B', 'C', 'E', 'G', 'H', 'O'), ('E', 'G', 'H', 'O')))
mro_merge((('E', 'G', 'H', 'F', 'O'), ('B', 'C', 'E', 'G', 'H', 'O'), ('E', 'G', 'H', 'O'))) = B + mro_merge((('E', 'G', 'H', 'F', 'O'), ('C', 'E', 'G', 'H', 'O'), ('E', 'G', 'H', 'O')))
mro_merge((('E', 'G', 'H', 'F', 'O'), ('C', 'E', 'G', 'H', 'O'), ('E', 'G', 'H', 'O'))) = C + mro_merge((('E', 'G', 'H', 'F', 'O'), ('E', 'G', 'H', 'O'), ('E', 'G', 'H', 'O')))
mro_merge((('E', 'G', 'H', 'F', 'O'), ('E', 'G', 'H', 'O'), ('E', 'G', 'H', 'O'))) = E + mro_merge((('G', 'H', 'F', 'O'), ('G', 'H', 'O'), ('G', 'H', 'O')))
mro_merge((('G', 'H', 'F', 'O'), ('G', 'H', 'O'), ('G', 'H', 'O'))) = G + mro_merge((('H', 'F', 'O'), ('H', 'O'), ('H', 'O')))
mro_merge((('H', 'F', 'O'), ('H', 'O'), ('H', 'O'))) = H + mro_merge((('F', 'O'), ('O',), ('O',)))
mro_merge((('F', 'O'), ('O',), ('O',))) = F + mro_merge((('O',), ('O',), ('O',)))
mro_merge((('O',), ('O',), ('O',))) = O + mro_merge(((), (), ()))
['D', 'B', 'C', 'E', 'G', 'H', 'F', 'O']