我对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__)
我得到了这个输出:
(<class '__main__.A'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.E'>, <class '__main__.G'>, <class '__main__.H'>, <class '__main__.F'>, <class 'object'>)
为什么我会在<class '__main__.C'>
之前获得<class '__main__.E'>
?
我以为会:
A
D
,B
,E
E
,F
| C
,H
| G
,H
等等
答案 0 :(得分:18)
简而言之,因为 C
取决于E
,因为您可以在依赖关系图中看到(O是object
):
Python的方法解析顺序(MRO)使用约束,即如果类 a 是类 b 的依赖关系,则它是放在队列中的后面是 b 。
现在更多的理论:
在Python中,MRO使用以下线性化规则:
L [
C(B1 ... Bn)
] = C +合并(L [B1
] ... L [Bn
],B1
... {{1 }});和L [
Bn
] =object
merge 定义为:
取第一个列表的头部,即L [
object
]B1
;如果这个头不在任何其他列表的尾部,那么将它添加到C的线性化并将其从合并中的列表中删除,否则查看下一个列表的头部并将其取出,如果它是好头。然后重复操作,直到所有课程都被删除或者找不到好头。在这种情况下,不可能构造合并,Python 2.3将拒绝创建类C并将引发异常。
因此,对于您的情况,第一步是:
L [[0]
] = A
+合并(L [A
],L [D
],L [B
])
让我们先解决递归调用:
L [E
] = D
+合并(L [D
],L [E
]);
L [F
] = B
+合并(L [B
],L [C
]);和
L [H
] = E
+合并(L [E
],L [G
])。
更多递归(我们只执行一次H
而不重做H
):
L [E
] = F
+合并(L [F
]);
L [O
] = C
+合并(L [C
],L [E
]);
L [G
] = G
+合并(L [G
]);和
L [O
] = H
+合并(L [H
])。
由于 L [O
] 是O
而合并(a)(对于一个对象 a )因此我们已经获得了O
,H
和G
的序列:
L [F
] =(H
,H
)。
L [O
] =(G
,G
)。
L [O
] =(F
,F
)。
现在我们可以计算 L [O
] :
L [E
] = E
+合并({E
,G
),(O
,H
) )
由于O
适用于尾部,因此它位于最后:
L [O
] =(E
,E
,G
,H
)。
现在我们可以计算 L [O
] :
L [C
] = C
+合并({C
,E
,G
,H
),( O
,G
));
L [O
] =(C
,C
)+合并({E
,G
,H
),({ {1}},O
));
L [G
] =(O
,C
,C
)+ merge((E
,G
),({ {1}}));
L [H
] =(O
,O
,C
,C
)+ merge((E
),({ {1}}));
* L [G
] =(H
,O
,O
,C
,C
)。
L [E
] :
L [G
] = H
+合并({O
,D
,D
,D
),( E
,G
));
..;
L [H
] =(O
,F
,O
,D
,D
,E
)< / em>的
下一步 L [G
] 可以完全解析:
L [H
] = F
+合并({O
,B
,B
,B
,{{ 1}}),(C
,E
));
..;
L [G
] =(H
,O
,H
,O
,B
,B
)< / em>的
现在我们终于可以解决了:
L [C
] = E
+合并({G
,H
,O
,A
,{{ 1}},A
),(D
,E
,G
,H
,F
,O
),( B
,C
,E
,G
));
L [H
] =(O
,E
)+合并({G
,H
,O
,{{1 },A
),(A
,D
,E
,G
,H
,F
),({ {1}},O
,B
,C
));
L [E
] =(G
,H
,O
)+ merge((E
,G
,{{1 },H
,O
),(A
,A
,D
,B
,E
),({ {1}},G
,H
,F
));
L [O
] =(C
,E
,G
,H
)+ merge((O
,{{1 }},E
,G
,H
),(O
,A
,A
,D
),({ {1}},B
,C
,E
));
L [G
] =(H
,F
,O
,E
,G
)+ merge(({{1 }},H
,O
,E
),(G
,H
,O
),(A
,{ {1}},A
));
L [D
] =(B
,C
,E
,G
,H
,F
)+合并({O
,G
,H
),(O
,G
),(H
,O
)) ;
L [A
] =(A
,D
,B
,C
,E
,G
,{ {1}})+合并({H
,F
),(O
),(H
));
L [O
] =(H
,O
,A
,A
,D
,B
,{ {1}},C
)+合并({E
),(G
),(H
));
L [F
] =(O
,O
,O
,A
,A
,D
,{ {1}},B
,C
)
预期的行为是什么。
我所做的效率不高的合并功能可以用于教育目的,它绝对没有针对制作进行优化:
E
当你调用它时,它会生成:
G