Method Resolve Order (MRO) - 类对象属性的解析顺序

Posted zzYzz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Method Resolve Order (MRO) - 类对象属性的解析顺序相关的知识,希望对你有一定的参考价值。


Method Resolve Order (MRO) - 类对象属性的解析顺序
Python 支持多重继承, 此时就需要解决按照何种顺序来解析属性的问题.
类的继承关系在一个特殊的类属性中指定(__mro__).这个属性的作用是按照序列出类及其超类, python 会按照这个顺利搜索方法。
任何实现了多重继承的语言都要处理潜在的命名冲突问题,这种冲突由不相关的父类实现的同名方法所引起的,称为‘菱形问题‘。

举个例子,
 1 class A(list):
 2     def disp(self):
 3         print(Class A - disp)
 4 
 5 class B(list):
 6     def disp(self):
 7         print(Class B - disp)
 8 
 9     def dispB(self):
10         print(Class B - dispB)
11 
12 class C(A):
13     pass
14 
15 class D(C, B):
16     pass
17 
18 if __name__ == __main__:
19     abc = D()
20     abc.disp()
21     abc.dispB()
22     print(D.__mro__)
23     print(C.__mro__)
24     print(B.__mro__)
25     print(A.__mro__)
26 
27 ‘‘‘
28 Output,
29     Class A - disp
30     Class B - dispB
31     (<class ‘__main__.D‘>, <class ‘__main__.C‘>, <class ‘__main__.A‘>, <class ‘__main__.B‘>, <class ‘list‘>, <class ‘object‘>)
32     (<class ‘__main__.C‘>, <class ‘__main__.A‘>, <class ‘list‘>, <class ‘object‘>)
33     (<class ‘__main__.B‘>, <class ‘list‘>, <class ‘object‘>)
34     (<class ‘__main__.A‘>, <class ‘list‘>, <class ‘object‘>)
35 ‘‘‘
D 的基类都实现了 disp 方法。当实例 abc 调用 disp() 方法的时候,是运行 A 或者 B 中的 disp 方法呢?
Python 内部首先完成对 D 这个类的 MRO 顺序的建立. 这个顺序存储在 D.__mor__ 属性中, 其为一个 tuple 对象,
依次存放着 class 对象. 这个 tuple 中 class 对象的顺序就是 Python 虚拟机在解析 D 这个类的属性时的顺序。
最终这个 tuple 将被保存在 PyTypeObject.tp_mro 中.

示例中各个类的继承顺序,
D -> C -> A -> B -> list -> object
C -> A -> list -> object
B -> list -> object
A -> list -> object

即,
(<class ‘__main__.D‘>, <class ‘__main__.C‘>, <class ‘__main__.A‘>, <class ‘__main__.B‘>, <class ‘list‘>, <class ‘object‘>)
(<class ‘__main__.C‘>, <class ‘__main__.A‘>, <class ‘list‘>, <class ‘object‘>)
(<class ‘__main__.B‘>, <class ‘list‘>, <class ‘object‘>)
(<class ‘__main__.A‘>, <class ‘list‘>, <class ‘object‘>)

注, MRO 设计到 ‘深度优先‘ 和 ‘广度优先‘ 两个概念.可以把这两个概念想象成两个维度. 深度优先 为 纵向维度, 广度优先 为 横向维度.

以示例为例,
D - C - B - list - object
| | | |
A list object object
| |
list object
|
object

在 横向上(广度优先概念), 如果实例 abc 调用 disp 方法, 最终会运行 class B 中的 disp 属性.
在 纵向上(深度优先概念), 如果实例 abc 调用 disp 方法, 最终会运行 class A 中的 disp 属性.
MRO 为 深度优先搜索
   

以上是关于Method Resolve Order (MRO) - 类对象属性的解析顺序的主要内容,如果未能解决你的问题,请参考以下文章

CodeChef - MRO Method Resolution Order(打表)

TypeError: Cannot create a consistent method resolution order (MRO) for bases P1, P2

Caused by: org.apache.ibatis.type.TypeException: Could not resolve type alias ‘order‘. Caus

Caused by: org.apache.ibatis.type.TypeException: Could not resolve type alias ‘order‘. Caus

如何在 Autofac 中的 scope.Resolve<Service<T>>().Method1() 中使用运行时类型参数?

在IDEA中的cannot_resolve_method解决方法