简而言之,因为C
依赖于取决于E
正如您在依赖图中看到的那样(O 是object
):
蟒蛇的方法解析顺序 (MRO)工作的约束条件是如果一个类a是一个类的依赖b,它被放置在队列中晚于b.
现在更多的是理论:
在 Python 中,MRO 使用以下内容线性化 rule:
L[C(B1 ... Bn)
] = C + 合并(L[B1
] ... L[Bn
], B1
... Bn
); and
L[object
] = object
(source)
And the merge定义为:
取第一个列表的头部,即 L[B1
][0]
;如果这个头不在任何其他列表的尾部,则将其添加到 C 的线性化中,并将其从合并的列表中删除,否则查看下一个列表的头并取出它,如果它是一个好头。然后重复操作,直到所有的类都被移除或者无法找到好的头。在这种情况下,不可能构造合并,Python 2.3 将拒绝创建 C 类并引发异常。
(source)
因此,对于您的情况,第一步是:
L[A
] = A
+ 合并(L[D
],L[B
],L[E
])
让我们首先解决递归调用:
L[D
] = D
+ 合并(L[E
],L[F
]);
L[B
] = B
+ 合并(L[C
],L[H
]); and
L[E
] = E
+ 合并(L[G
],L[H
]).
还有更多的递归(我们只做H
一次并且不要重做E
):
L[F
] = F
+ 合并(L[O
]);
L[C
] = C
+ 合并(L[E
],L[G
]);
L[G
] = G
+ 合并(L[O
]); and
L[H
] = H
+ 合并(L[O
]).
Since L[O
] is O
and merge(a)(对于一个对象是a)因此我们已经获得了序列H
, G
and F
:
L[H
] = (H
, O
).
L[G
] = (G
, O
).
L[F
] = (F
, O
).
现在我们可以计算L[E
]:
L[E
] = E
+合并((G
,O
) , (H
,O
) ).
Since 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
).
And L[D
]:
L[D
] = D
+合并((E
,G
,H
,O
) , (F
,O
) );
..;
L[D
] = (D
,E
,G
,H
,F
,O
).
Next 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
,C
,E
,G
,H
,O
) , (E
,G
,H
,O
) );
L[A
] = (A
,D
,B
) + 合并( (E
,G
,H
,F
,O
) , (C
,E
,G
,H
,O
) , (E
,G
,H
,O
) );
L[A
] = (A
,D
,B
,C
) + 合并( (E
,G
,H
,F
,O
) , (E
,G
,H
,O
) , (E
,G
,H
,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
,D
,B
,C
,E
,G
,H
) + 合并( (F
,O
) , (O
) , (O
) );
L[A
] = (A
,D
,B
,C
,E
,G
,H
,F
) + 合并( (O
) , (O
) , (O
) );
L[A
] = (A
,D
,B
,C
,E
,G
,H
,F
,O
).
这是预期的行为。
A 效率不高我制作的合并函数可用于教育目的,它绝对没有针对生产进行优化:
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']