简而言之,因为C
取决于E
您在依赖图中看到的 (O is object
):
Python 的方法解析顺序 (MRO)的约束条件是,如果类a是类b的依赖项,则它在队列中的放置时间比b晚。
现在更多的理论:
在 Python 中,MRO 使用以下线性化规则:
L[ C(B1 ... Bn)
] = C + 合并(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
+ 合并(L[ E
],L[ F
]) ;
L[ B
] = B
+ 合并(L[ C
],L[ H
]) ; 和
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
]) ; 和
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
+ 合并( ( 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']