• Python MRO


    文中代码基于Python3.7

     

    对于Python中的多继承情况,运行时在搜索对象的属性或方法时,需要遵循一定的顺序规则,这个规则称为:Method Resolution Order (MRO).

     

    MRO规则可以总结为以下三句话:

    • In the multiple inheritance scenario, any specified attribute is searched first in the current class. If not found, the search continues into parent classes in depth-first, left-right fashion without searching the same class twice.

    • So, first it goes to super class (and its super classes) given first in the list then second super class (and its super classes) , from left to right order. Then finally Object class, which is a super class for all classes.

      这里的list指的是多个父类组成的list,如:

      class M(X,Y,Z):

      pass

      list就是(X,Y,Z)

    • When in MRO we have a super class before subclass then it must be removed from that position in MRO.

      这一句和第一句对应起来看,一个类只被检索一次,所以基类要往后移

     

    可以调用类型对象的mro方法或者__mro__属性来获取类型的MRO信息。

     

    class X:
        def hello(self):
            print('x')
    ​
    ​
    class Y:
        def hello(self):
            print('y')
        
        def world(self):
            print('y_world')
    ​
    ​
    class Z:
        def hello(self):
            print('z')
    ​
    ​
    class A(X):
        def hello(self):
            print('a')
    ​
    ​
    class B(Y,Z):
        def hello(self):
            print('b')
    ​
    ​
    class M(B, A): 
        passprint(M.mro())
    print(M.__mro__)
    ​
    # 输出:
    # list类型
    [<class '__main__.M'>, <class '__main__.B'>, <class '__main__.Y'>, <class '__main__.Z'>, <class '__main__.A'>, <class '__main__.X'>, <class 'object'>]
    # tuple类型
    (<class '__main__.M'>, <class '__main__.B'>, <class '__main__.Y'>, <class '__main__.Z'>, <class '__main__.A'>, <class '__main__.X'>, <class 'object'>)

    MRO图示如下:

    goes to super class (and its super classes) given first in the list then second super class (and its super classes) , from left to right order. Then finally Object class

    depth-first, left-right fashion without searching the same class twice ,得到MRO列表:[<class '__main__.M'>, <class '__main__.B'>, <class '__main__.Y'>, <class '__main__.Z'>, <class '__main__.A'>, <class '__main__.X'>, <class 'object'>]

     


     

    B和A均继承自Z,M继承自B和A:

    class X:
        def hello(self):
            print('x')
    ​
    ​
    class Y:
        def hello(self):
            print('y')
        
        def world(self):
            print('y_world')
    ​
    ​
    class Z:
        def hello(self):
            print('z')
    ​
    ​
    class A(X,Z):
        def hello(self):
            print('a')
    ​
    ​
    class B(Y,Z):
        def hello(self):
            print('b')
    ​
    ​
    class M(B, A): 
        passprint(M.mro())
    ​
    # 输出:
    # [<class '__main__.M'>, <class '__main__.B'>, <class '__main__.Y'>, <class '__main__.A'>, <class '__main__.X'>, <class '__main__.Z'>, <class 'object'>]

    MRO图示如下:

    goes to super class (and its super classes) given first in the list then second super class (and its super classes) , from left to right order. Then finally Object class

    depth-first, left-right fashion without searching the same class twice ,得到MRO列表:[<class '__main__.M'>, <class '__main__.B'>, <class '__main__.Y'>, <class '__main__.A'>, <class '__main__.X'>, <class '__main__.Z'>, <class 'object'>]

     


     

    class X:
        def hello(self):
            print('x')
    ​
    ​
    class Y:
        def hello(self):
            print('y')
        
        def world(self):
            print('y_world')
    ​
    ​
    class Z:
        def hello(self):
            print('z')
    ​
    ​
    class A(X,Z):
        def hello(self):
            print('a')
    ​
    ​
    class B(Y,Z):
        def hello(self):
            print('b')
    ​
    ​
    class M(B, A, Y): 
        passprint(M.mro())
    ​
    # 输出
    # [<class '__main__.M'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.Y'>, <class '__main__.X'>, <class '__main__.Z'>, <class 'object'>]

    MRO图示如下:

    goes to super class (and its super classes) given first in the list then second super class (and its super classes) , from left to right order. Then finally Object class

    这个MRO图可以继续简化:

    depth-first, left-right fashion without searching the same class twice

     

    得到MRO列表为[<class '__main__.M'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.Y'>, <class '__main__.X'>, <class '__main__.Z'>, <class 'object'>]

     


     

    When in MRO we have a super class before subclass then it must be removed from that position in MRO

     

    下面是一个会报错的示例:

    class A:
        def process(self):
            print('A process()')
    ​
    ​
    class B(A):
        def process(self):
            print('B process()')
    ​
    ​
    class M(A, B):
        passprint(M.mro())
    ​
    # 输出:
    # TypeError: Cannot create a consistent method resolution
    # order (MRO) for bases A, B

    MRO图示:

    如果一个方法或属性同时存在与B和A,应为M直接继承B又直接继承A,那么通过M来调用时就不知道是该从B中还是A中获取这个方法或属性了,干脆就报错吧。我觉得MRO顺序应该为:M->B->A->object。

    推荐阅读

    Python Multiple Inheritance

    Method Resolution Order (MRO) in Python

  • 相关阅读:
    VUE脚手架,babel转码 常用命令
    ES6那些事半功倍的新特性(一)
    vuex中怎么把‘库’中的状态对象赋值给内部对象(三种方法)
    VUE自定义指令生命周期,VUE生命周期
    判断是数组还是对象的方法
    利用cordova打包H5混合app
    webstorm皮肤外观样式快速设置,CMD的使用方法,webstorm11激活方法
    数组操作方法中的splice()和concat() 以及slice()
    Angularjs跨域
    Node.js的基础知识(一)
  • 原文地址:https://www.cnblogs.com/Cwj-XFH/p/13166808.html
Copyright © 2020-2023  润新知