在 Python 中用到多继承时,调用父类方法很容易出错:父类方法调用了多次,只能通过__mro__魔法方法来获取调用顺序,花了点时间了解其中涉及的排序算法,顺带记录
- 拓扑排序
在了解 MRO 排序算法之前,先了解下拓扑排序(以下摘自维基百科)
在图论中,由一个有向无环图的顶点组成的序列,当且仅当满足下列条件时,称为该图的一个拓扑排序(英语:Topological sorting)。
1.每个顶点出现且只出现一次;
2.若A在序列中排在B的前面,则在图中不存在从B到A的路径。
说人话,看下面的图就明白了 (图片搬运自别人的博客,画的很不错我直接拿来用了,链接在文章末尾),图中每个点都是有指向性的:可能指向别人或者被别人指向。
拓扑顺序就是:每次找到一个只指向别人的点 (学术性说法:入度为0),记录下来;然后忽略掉这个点和它所指出去的线,再找到下一个只指向别人的点,记录下来,直到剩最后一个点,所有记录的点的顺序就是拓扑顺序
上图中,只有点1只指向别人,输出1;去掉点1和它伸出的两根线外只有点2只指向别人,输出2;…类推下去,得到拓扑排序结构: 1 2 4 3 5
2. MRO 排序算法
MRO 排序应用了 C3 算法,想了解 C3 自己查吧…总之得到的结果类似于拓扑排序,下面有段简单的多继承代码和其对应的拓扑排序的抽象图 (所用代码实例和图片均来应用自别处,文章末尾有链接)
class D(object):
pass
class E(object):
pass
class F(object):
pass
class C(D, F):
pass
class B(E, D):
pass
class A(B, C):
pass
if __name__ == '__main__':
print A.__mro__
得到的输出结果:
(<class ‘main.A’>, <class ‘main.B’>, <class ‘main.E’>, <class ‘main.C’>, <class ‘main.D’>, <class ‘main.F’>, <type ‘object’>)
下面就是抽象出来的图
我们就用拓扑排序来分析,但是这里会碰到同时存在好几个点都是入度为0 (说人话,就是没有被别人指向的点),这时按照树的排序来,即从左到右,从根到叶,这里 A 就是根。
所以具体情况就是:我们先找到了点 A只有它没有被别人指向,输出A;去掉A及其伸出的两条线,剩 B 和 C 点同时满足只指向别人,按照树的顺序从左到右,故先输出B;去掉线剩 E 和 C ,输出E ;去线剩 C,输出C;去线剩 D 和 F ,输出D;去线只剩F ,输出F;最后输出object;得到的输出结果:
A B E C D F object
对比系统打印出的结果,顺序是一致的。这样下次你就可以装逼地手动计算多继承时调用类的顺序了 (好像没啥卵用~)
作者:大白杏仁
链接:https://www.jianshu.com/p/6651ed35104c
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
来源:https://blog.csdn.net/musecangying008/article/details/100668863