一、 mro查找定义

如果多个类继承父类,然后又被多个类继承这种复杂的问题,可以使用mro方法

class D:pass
class C(D):pass
class B(D):pass
class  A(B,C):passprint(A.__mro__)
输出结果:
(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>)

二、 mro查找应用

自从Python2.3后使用C3 MRO算法,关于C3 MRO算法的详情,参考The Python 2.3 Method Resolution Order

MRO结果 深度优先搜索DFS  广度优先搜索BFS 
图一 A->B->D->C->E  A->B->C->D->E 
图二 A->B->D->C  A->B->C->D 

DFS:对应图2菱形继承有问题。加入现在有一个方法get_value, C、D中存在get_value, A、B不存在get_value, 那么当A调用get_value时,调用的就是D中的get_value方法。C中永远起不到重载D中方法的作用。因此DFS对菱形继承有问题,在python2之后改为了广度优先算法。

BFS:图2的菱形继承问题解决了,但是图1的继承又出现了问题。 以图1来说明,如果C和D中有一个同名的方法get_value, B和A中没有get_value方法,那么A调用get_value时,就会调用C中的方法,而实际上B和D应该看成一个整体,在B中不存在就应该去父类中搜索。因此在Python2.3后,提出了C3 MRO算法,解决了上面的两个问题。

那么如何查看C3 MRO算法的搜索顺序呢, 调用__mro__属性

图1:
class D(object):passclass E(object):passclass B(D):passclass C(E):pass
class A(B, C):passprint(A.__mro__)
#MRO顺序:A-->B-->D-->C-->E
#结果:(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.C'>, <class '__main__.E'>, <class 'object'>)
图2class D(object):passclass B(D):passclass C(D):pass
class A(B, C):passprint(A.__mro__)
# MRO顺序:A-->B-->C-->D
#结果:(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>)

Python2.3到Python2.7:经典类、新式类和平发展
因为之前的BFS存在较大的问题,所以从Python2.3开始新式类的MRO取而代之的是C3算法,我们可以知道C3算法肯定解决了单调性问题,和只能继承无法重写的问题。C3算法具体实现稍后讲解。
MRO的C3算法顺序如下图:看起简直是DFS和BFS的合体有木有。但是仅仅是看起来像而已

三、 C3算法原理

Python3到至今:新式类一统江湖
Python3开始就只存在新式类了,采用的MRO也依旧是C3算法。

我们要解决两个问题:单调性问题和不能重写的问题。
很容易发现要解决单调性,只要保证从根(A)到叶(object),从左到右的访问顺序即可。
那么对于只能继承,不能重写的问题呢?先分析这个问题的本质原因,主要是因为先访问了子类的父类导致的。那么怎么解决只能先访问子类再访问父类的问题呢?如果熟悉图论的人应该能马上想到拓扑排序,这里引用一下百科的的定义:
对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。
因为拓扑排序肯定是根到叶(也不能说是叶了,因为已经不是树了),所以只要满足从左到右,得到的拓扑排序就是结果,关于拓扑排序算法,大学的数据结构有教,这里不做讲解,不懂的可以自行谷歌或者翻一下书,建议了解完算法再往下看。
那么模拟一下例子的拓扑排序:首先找入度为0的点,只有一个A,把A拿出来,把A相关的边剪掉,再找下一个入度为0的点,有两个点(B,C),取最左原则,拿B,这是排序是AB,然后剪B相关的边,这时候入度为0的点有E和C,取最左。这时候排序为ABE,接着剪E相关的边,这时只有一个点入度为0,那就是C,取C,顺序为ABEC。剪C的边得到两个入度为0的点(DF),取最左D,顺序为ABECD,然后剪D相关的边,那么下一个入度为0的就是F,然后是object。那么最后的排序就为ABECDFobject。

对比一下 A.__mro__的结果(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.D'>, <class '__main__.F'>, <type 'object'>)

参考文章:

MRO算法

4-6 类和实例属性的查找顺序----mro查找

Python高级编程:类和实例属性的查找顺序—mro查找相关推荐

  1. python编程例子-Python面向对象编程 - 类和实例

    一.preface 面向对象编程OOP:object oriented programming. OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数.Python是一门面向对象的编程语 ...

  2. python对象编程例子-python 面向对象编程 类和实例

    class Student(object): #class后面紧接着是类名,即Student,类名通常是大写开头的单词,紧接着是(object),表示该类是从哪个类继承下来的.通常,如果没有合适的继承 ...

  3. python高级编程 豆瓣_《Python高级编程》读书笔记:方法解释顺序浅析

    Python在2.2引入了New-style object(ref),而且在2.3引入了新的方法解释顺序(Method resolution order,以下简称MRO),新的MRO解决了多继承下的方 ...

  4. python高级编程(3) - 深入类和多态

    深入类和多态 一,鸭子类型和多态 鸭子类型 当你看到一只鸟走起来想鸭子,游泳起来像鸭子,叫起来像鸭子,那么这只鸟就叫做鸭子类型 我们并不关心对象是什么类型,到底是不是鸭子,只关心行为. 我们只关心一个 ...

  5. python队列线程池_实例详解:python高级编程之消息队列(Queue)与进程池(Pool)

    今天为大家带来的内容是:python高级编程之消息队列(Queue)与进程池(Pool),结合了实例的形式详细分析了Python消息队列与进程池的相关原理.使用技巧与操作注意事项!!! Queue消息 ...

  6. Python 高级编程笔记之类别

    目录: 子类化内建类型 访问超类中的方法-super 描述符 & 属性 元编程 主要内容: 1.子类化内建类型 # -*- coding:utf-8 -*-class Folder(list) ...

  7. python数据符号函数等一切皆对象_第一章:Python高级编程-Python一切皆对象

    第一章:Python高级编程-Python一切皆对象 Python3高级核心技术97讲 笔记 1. Python一切皆对象 1.1 函数和类也是对象,属于Python的一等公民 "" ...

  8. python高级编程-网络编程、多任务

    python高级编程 1 IP地址 用来在网络中标记一台电脑:在本地局域网上是唯一的. 2 端口 一个程序需要收发网络数据,就需要端口号. 3 socket 创建socket # 创建tcp sock ...

  9. 4万字【Python高级编程】保姆式教学,进阶感觉到吃力?学完这些就轻松了

    前几天和一个小伙子聊天时,发现了一个问题,他从零开始学Python,学完列表.字典和函数等基础之后,就开始往爬虫方向进阶学习,结果又花了一个多月的时间,啥也没学成,反而寸步难行. 其实这个问题的主要原 ...

最新文章

  1. 净化心灵的诗歌--《当你老了》
  2. mysql 8.3_8.3 - mysql 表操作
  3. mdl格式是什么软件生成的_Mac 上有什么好的视频格式转换软件?
  4. 七夕过后,你分析过自己单身原因的原因吗?
  5. mysql远程服务器访问数据库
  6. Codeforces 991E. Bus Number (DFS+排列组合)
  7. 收藏一些自己认为好的网站或博客
  8. Linux shell编程中read参数说明
  9. git 删除已经 add 的文件
  10. 在SSRS报表中,显示图片
  11. 无法创建堆栈的防护页面 解决方法
  12. linux 可道云_腾讯云linux+kodexplorer可道云搭建私有云盘
  13. java清除不掉cookie,java清除cookie
  14. win7升级win10后周期性蓝屏问题解决(经过2个月的测试观察,电脑没有再出现蓝屏)
  15. 如何实现多列对比去重
  16. TableView的使用方法
  17. Java+Jsp+MySql实现图书管理系统_图书管理系统代码
  18. 付给铁匠的账单 数据结构
  19. android 组件可见,android界面控件可见性方法setVisibility()3个可选参数(visible,invisible,gone)的区别...
  20. 清理autodesk产品注册表_如何完整移除Autodesk的产品?

热门文章

  1. 巧用句柄函数:闪烁窗体,做提示功能时很有用哦
  2. VS2010 创建WindowsService服务
  3. vscode使用sftp同步服务器文件
  4. NSIS打包软件使用
  5. LightOJ - 1027 数学期望
  6. 如何在新浪博客中添加JavaScript代码
  7. Ext JS高级程序设计
  8. 看似无参却有参-----JS中的函数传参
  9. iptables中关于limit和limit-burst的解释
  10. swift:创建表格UITableView