Method Resolve Order (MRO) - 类对象属性的解析顺序
Python 支持多重继承, 此时就需要解决按照何种顺序来解析属性的问题.
类的继承关系在一个特殊的类属性中指定(__mro__).这个属性的作用是按照序列出类及其超类, python 会按照这个顺利搜索方法。
任何实现了多重继承的语言都要处理潜在的命名冲突问题,这种冲突由不相关的父类实现的同名方法所引起的,称为'菱形问题'。 举个例子,
 class A(list):
def disp(self):
print('Class A - disp') class B(list):
def disp(self):
print('Class B - disp') def dispB(self):
print('Class B - dispB') class C(A):
pass class D(C, B):
pass if __name__ == '__main__':
abc = D()
abc.disp()
abc.dispB()
print(D.__mro__)
print(C.__mro__)
print(B.__mro__)
print(A.__mro__) '''
Output,
Class A - disp
Class B - dispB
(<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'>)
'''
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 是 深度优先搜索
 
  

最新文章

  1. Solr学习总结(三)Solr web 管理后台
  2. 32-bit Assembly on x86_64 Linux (Use Nasm and ld&amp;gcc)
  3. POJ3162 Walking Race(树形DP+尺取法+单调队列)
  4. Mysql复制-Slave库设置复制延迟
  5. Java基础之创建窗口——使用网格布局管理器(TryGridLayout)
  6. Sqli-labs less 63
  7. HDU 1890--Robotic Sort(Splay Tree)
  8. 工作总结:MFC使用Windows自带打开对话框
  9. 【问题解决】syntax error: unexpected end of file或-bash: ./full_build.sh: /bin/bash^M: bad interpreter: No
  10. ASP.NET Web API是如何根据请求选择Action的?[上篇]
  11. 如何使用LIBSVM,从安装到基本实例使用
  12. Linux中dos2unix批量转换
  13. JS处理日期&amp;字符串格式相互转换
  14. vue form表单验证
  15. .net core 中间件实战
  16. codeforces580C
  17. Ultraedit使用小技巧
  18. 跟着百度学PHP[11]-PHP当中的异常处理
  19. WP的SEO工具汇总
  20. windows查看指定端口

热门文章

  1. webpack实践——DLLPlugin 和 DLLReferencePlugin的使用
  2. 3 分钟带你深入了解 Cookie、Session、Token
  3. Java类成员之构造器
  4. DP-01背包 (题)
  5. (数据科学学习手札73)盘点pandas 1.0.0中的新特性
  6. [bzoj5507] [洛谷P5305] [gzoi2019]旧词
  7. Treap基本用法总结
  8. qt中的拖拽及其使用技巧
  9. Jmeter使用—使用 HTTP代理服务器抓取接口
  10. SpringBoot项目的parent依赖和配置文件*.properties、*.yml详解