• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    Python学习之MRO方法搜索顺序

    为什么会讲 MRO?

    什么是 MRO

    实际代码

    class A:
        def test(self):
            print("AAA-test")
    
    
    class B:
        def test(self):
            print("BBB-test")
    
    
    # 继承了三个类,B、A、还有默认继承的 object
    class C(B, A):
        ...
    
    
    # 通过类对象调用,不是实例对象!
    print(C.__mro__)
    
    
    

    # 输出结果
    (class '__main__.C'>, class '__main__.B'>, class '__main__.A'>, class 'object'>)

    类图

    注意

    其实 MRO 是涉及一个底层算法的,下面来详细讲解一下

    MRO 算法

    Python 发展到现在经历了三种算法

    什么是旧式类,新式类

    Python学习之新式类和旧式类讲解

    想深入了解 C3 算法的可以看看官网

    https://www.python.org/download/releases/2.3/mro/

    旧式类 MRO 算法

    需要在 python2 环境下运行这段代码

    实际代码

    # 旧式类算法
    class A:
        def test(self):
            print("CommonA")
    
    
    class B(A):
        pass
    
    
    class C(A):
        def test(self):
            print("CommonC")
    
    
    class D(B, C):
        pass
    
    
    D().test()
    
    
    

    # python2 下的运行结果
    CommonA

    类图

    分析

    新式类 MRO 算法

    以上面的代码栗子来讲

    新式 MRO 算法的问题

    虽然解决了旧式 MRO 算法的问题,但可能会违反单调性原则

    什么是单调性原则?

    在子类存在多继承时,子类不能改变父类的 MRO 搜索顺序,否则会导致程序发生异常

    实际代码

    class X(object):
        pass
    
    
    class Y(object):
        pass
    
    
    class A(X, Y):
        pass
    
    
    class B(Y, X):
        pass
    
    
    class C(A, B):
        pass

    深度优先遍历后的搜索顺序为:C->A->X->object->Y->object->B->Y->object->X->object

    相同取后者的搜索顺序为:C->A->B->Y->X->object

    分析不同类的 MRO

    很明显,B、C 中间的 X、Y 顺序是相反的,就是说 B 被继承时,它的搜索顺序会被改变,违反了单调性

    在 python2 中运行这段代码的报错

    在 python3 中运行这段代码的报错

    C3 MRO 算法

    将上面第一个栗子的代码放到 python3 中运行

    class A:
        def test(self):
            print("CommonA")
    
    
    class B(A):
        pass
    
    
    class C(A):
        def test(self):
            print("CommonC")
    
    
    class D(B, C):
        pass
    
    
    D().test()
    
    
    

    # 输出结果
    CommonC

    简单了解下 C3 算法

    以上面代码为栗子,C3 会把各个类的 MRO 等价为以下等式

    了解一下:头、尾

    以 A 类为栗,merge() 包含的 A 成为 L[A] 的头,剩余元素(这里只有 object)称为尾

    merge 的运算方式

    重复以上步骤直到列表为空,则算法结束;如果不能再找出可以输出的元素,则抛出异常

    简单类 MRO 的计算栗子

    class B(object): pass
    
    print(B.__mro__)
    
    
    (class '__main__.B'>, class 'object'>)
    L[B] = L[B(object)]
         = B + merge(L[object])
         = B + L[object]
         = B object

    单继承MRO 的计算栗子

    # 计算 MRO
    class B(object): pass
    
    class C(B): pass
    
    print(C.__mro__)
    
    
    (class '__main__.C'>, class '__main__.B'>, class 'object'>)
    L[C] = C + merge(L[B])
         = C + L[B]
         = C B object

    多继承MRO 的计算栗子

    O = object
    
    class F(O): pass
    
    class E(O): pass
    
    class D(O): pass
    
    class C(D, F): pass
    
    class B(D, E): pass
    
    class A(B, C): pass
    
    
    print(C.__mro__)
    print(B.__mro__)
    print(A.__mro__)
    
    
    

    # 输出结果
    (class '__main__.C'>, class '__main__.D'>, class '__main__.F'>, class 'object'>)
    (class '__main__.B'>, class '__main__.D'>, class '__main__.E'>, class 'object'>)
    (class '__main__.A'>, class '__main__.B'>, class '__main__.C'>, class '__main__.D'>, class '__main__.E'>, class '__main__.F'>, class 'object'>)

    L[O] = O = object
    L[D] = D + merge(L[O])
            = D O
    L[C] = L[C(D, F)]
         = C + merge(L[D], L[F], DF)
         # 从前面可知 L[D] 和 L[F] 的结果
         = C +  merge(DO, FO, DF)
         # 因为 D 是顺序第一个并且在几个包含 D 的 list 中是 head,
         # 所以这一次取 D 同时从列表中删除 D
         = C + D + merge(O, FO, F)
         # 因为 O 虽然是顺序第一个但在其他 list (FO)中是在尾部, 跳过
         # 改为检查第二个list FO
         # F 是第二个 list 和其他 list 的 head
         # 取 F 同时从列表中删除 F
         = C + D + F + merge(O)
         = C D F O
    L[B] = L[B(D, E)]
         = B + merge(L[D], L[E], DE)
         = B + merge(DO, EO, DE)
         = B + D + merge(O, EO, E)
         = B + D + E + merge(O)
         = B D E O
    L[A] = L[A(B,C)]
            = A + merge(L[B], L[C], BC)
            = A + merge( BDEO, CDFO, BC )
            = A + B + merge( DEO, CDFO, C )
            # D 在其他列表 CDFO 不是 head,所以跳过到下一个列表的 头元素 C
            = A + B + C + merge( DEO, DFO )
            = A + B + C + D + merge( EO, FO )
            = A + B + C + D + E + merge( O, FO )
            = A + B + C + D + E + F + merge( O )
            = A B C D E F O

    多继承MRO 的计算栗子二

    O = object
    
    class F(O): pass
    
    class E(O): pass
    
    class D(O): pass
    
    class C(D, F): pass
    
    class B(E, D): pass
    
    class A(B, C): pass
    
    
    print(C.__mro__)
    print(B.__mro__)
    print(A.__mro__)
    
    
    

    # 输出结果
    (class '__main__.C'>, class '__main__.D'>, class '__main__.F'>, class 'object'>)
    (class '__main__.B'>, class '__main__.E'>, class '__main__.D'>, class 'object'>)
    (class '__main__.A'>, class '__main__.B'>, class '__main__.E'>, class '__main__.C'>, class '__main__.D'>, class '__main__.F'>, class 'object'>)

    L[O] = O = object
    L[D] = D + merge(L[O])
            = D O
    L[C] = L[C(D, F)]
            = C + merge(L[D], L[F], DF)
            = C + merge(DO, FO, DF)
            = C + D + merge(O, FO, F)
            = C + D + F + merge(O)
            = C D F O
    L[B] = L[B(E, D)]
           = B + merge(L[E], L[D], ED)
           = B + merge(EO, DO, ED)
           = B + E + merge(O, DO, D)
           = B + E + D + merge(O)
           = B E D O
    L[A]  = L[A(B, C)]
            = A + merge(L[B], L[C], BC)
            = A + merge(BEDO, CDFO, BC)
            = A + B + merge(EDO, CDFO, C)
            = A + B + E + merge(DO,CDFO, C)
            = A + B + E + C + merge(O,DFO)
            = A + B + E + C + D + merge(O, FO)
            = A + B + E + C + D + F + merge(O)
            = A B E C D F O

    到此这篇关于Python学习之MRO方法搜索顺序的文章就介绍到这了,更多相关Python MRO方法搜索顺序内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    您可能感兴趣的文章:
    • 浅谈Python的方法解析顺序(MRO)
    • Python高级编程之继承问题详解(super与mro)
    • Python多继承以及MRO顺序的使用
    上一篇:分析python垃圾回收机制原理
    下一篇:Python如何用str.format()批量生成网址(豆瓣读书为例)
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    Python学习之MRO方法搜索顺序 Python,学,习之,MRO,方法,搜索,