我有Python MRO的问题对于这段代码:
class F: pass class G: pass class H: pass class E(G,H): pass class D(E,F): pass class C(E,G): pass class B(C,H): pass class A(D,B,E): pass print(A.__mro__)
我得到这个输出:
(
我为什么要来
之前
?
我以为会是:
A
D
,B
,E
E
,F
| C
,H
| G
,H
等等
总之,因为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
(资源)
而合并被定义为:
取第一个清单的头部,即L [
B1
][0]
; 如果这个头不在任何其他列表的尾部,那么将它添加到C的线性化并将其从合并中的列表中删除,否则查看下一个列表的头部并将其取出,如果它是好头.然后重复操作,直到所有课程都被删除或者找不到好头.在这种情况下,不可能构造合并,Python 2.3将拒绝创建类C并将引发异常.
(资源)
所以对于你的情况来说,第一步是:
L [ A
] = A
+合并(L [ D
],L [ B
],L [ E
])
我们先解决递归调用:
L [ D
] = D
+ merge(L [ E
],L [ F
]) ;
L [ B
] = B
+ merge(L [ C
],L [ H
]) ; 和
L [ E
] = E
+合并(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
+合并(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
+ merge((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
,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
.
这是预期的行为.
我所做的一个非常有效的合并功能可以用于教育目的,它绝对没有针对生产进行优化:
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']