• Python中MRO排序原理


    在 Python 中用到多继承时,调用父类方法很容易出错:父类方法调用了多次,只能通过__mro__魔法方法来获取调用顺序,花了点时间了解其中涉及的排序算法,顺带记录

    1. 拓扑排序

    在了解 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
    

    对比系统打印出的结果,顺序是一致的。这样下次你就可以装逼地手动计算多继承时调用类的顺序了 (好像没啥卵用~)



  • 相关阅读:
    CLSCompliantAttribute
    杂言
    批处理修改目录的隐藏属性
    unittest基本用法
    unittest跳过用例
    MySQL流程控制结构
    MySQL视图
    MySQL函数
    unittest断言 & 数据驱动
    PLSQL
  • 原文地址:https://www.cnblogs.com/sea520/p/11270448.html
Copyright © 2020-2023  润新知