python多重继承新算法C3介绍


Posted in Python onSeptember 28, 2014

mro即 method resolution order (方法解释顺序),主要用于在多继承时判断属性的路径(来自于哪个类)。

在python2.2版本中,算法基本思想是根据每个祖先类的继承结构,编译出一张列表,包括搜索到的类,按策略删除重复的。但是,在维护单调性方面失败过(顺序保存),所以从2.3版本,采用了新算法C3。

为什么采用C3算法

C3算法最早被提出是用于Lisp的,应用在Python中是为了解决原来基于深度优先搜索算法不满足本地优先级,和单调性的问题。

本地优先级:指声明时父类的顺序,比如C(A,B),如果访问C类对象属性时,应该根据声明顺序,优先查找A类,然后再查找B类。

单调性:如果在C的解析顺序中,A排在B的前面,那么在C的所有子类里,也必须满足这个顺序。

C3算法

判断mro要先确定一个线性序列,然后查找路径由由序列中类的顺序决定。所以C3算法就是生成一个线性序列。

如果继承至一个基类:

class B(A)

这时B的mro序列为[B,A]

如果继承至多个基类

class B(A1,A2,A3 ...)

这时B的mro序列 mro(B) = [B] + merge(mro(A1), mro(A2), mro(A3) ..., [A1,A2,A3])
merge操作就是C3算法的核心。

遍历执行merge操作的序列,如果一个序列的第一个元素,是其他序列中的第一个元素,或不在其他序列出现,则从所有执行merge操作序列中删除这个元素,合并到当前的mro中。

merge操作后的序列,继续执行merge操作,直到merge操作的序列为空。

如果merge操作的序列无法为空,则说明不合法。

例子:

class A(O):pass

class B(O):pass

class C(O):pass

class E(A,B):pass

class F(B,C):pass

class G(E,F):pass

A、B、C都继承至一个基类,所以mro序列依次为[A,O]、[B,O]、[C,O]

mro(E) = [E] + merge(mro(A), mro(B), [A,B])

       = [E] + merge([A,O], [B,O], [A,B])

执行merge操作的序列为[A,O]、[B,O]、[A,B]

A是序列[A,O]中的第一个元素,在序列[B,O]中不出现,在序列[A,B]中也是第一个元素,所以从执行merge操作的序列([A,O]、[B,O]、[A,B])中删除A,合并到当前mro,[E]中。
mro(E) = [E,A] + merge([O], [B,O], [B])

再执行merge操作,O是序列[O]中的第一个元素,但O在序列[B,O]中出现并且不是其中第一个元素。继续查看[B,O]的第一个元素B,B满足条件,所以从执行merge操作的序列中删除B,合并到[E, A]中。

mro(E) = [E,A,B] + merge([O], [O])

       = [E,A,B,O]

实现C3算法的代码

#-*- encoding:GBK -*-#  

def mro_C3(*cls):  

        if len(cls)==1:  

            if not cls[0].__bases__:  

                return  cls  

            else:  

                return cls+ mro_C3(*cls[0].__bases__)  

        else:  

            seqs = [list(mro_C3(C)) for C in cls ] +[list(cls)]  

            res = []  

            while True:  

              non_empty = list(filter(None, seqs))  

              if not non_empty:  

                  return tuple(res)  

              for seq in non_empty:  

                  candidate = seq[0]  

                  not_head = [s for s in non_empty if candidate in s[1:]]  

                  if not_head:  

                      candidate = None  

                  else:  

                      break  

              if not candidate:  

                  raise TypeError("inconsistent hierarchy, no C3 MRO is possible")  

              res.append(candidate)  

              for seq in non_empty:  

                  if seq[0] == candidate:  

                      del seq[0]

Python 相关文章推荐
Python通过websocket与js客户端通信示例分析
Jun 25 Python
python求解水仙花数的方法
May 11 Python
Python如何获取系统iops示例代码
Sep 06 Python
详解django中自定义标签和过滤器
Jul 03 Python
python matplotlib画图实例代码分享
Dec 27 Python
Python实现TCP探测目标服务路由轨迹的原理与方法详解
Sep 04 Python
Matplotlib自定义坐标轴刻度的实现示例
Jun 18 Python
Python docutils文档编译过程方法解析
Jun 23 Python
Python接口自动化系列之unittest结合ddt的使用教程详解
Feb 23 Python
Python OpenCV快速入门教程
Apr 17 Python
手残删除python之后的补救方法
Jun 26 Python
浅谈Python中对象是如何被调用的
Apr 06 Python
wxPython窗口的继承机制实例分析
Sep 28 #Python
wxPython框架类和面板类的使用实例
Sep 28 #Python
Python的加密模块md5、sha、crypt使用实例
Sep 28 #Python
wxPython学习之主框架实例
Sep 28 #Python
python实现得到一个给定类的虚函数
Sep 28 #Python
python实现根据图标提取分类应用程序实例
Sep 28 #Python
wxPython事件驱动实例详解
Sep 28 #Python
You might like
PHP 和 MySQL 开发的 8 个技巧
2006/10/09 PHP
PHP安全的URL字符串base64编码和解码
2014/06/19 PHP
PHP水印类,支持添加图片、文字、填充颜色区域的实现
2017/02/04 PHP
PHP+Redis开发的书签案例实战详解
2019/07/09 PHP
php操作redis数据库常见方法实例总结
2020/02/20 PHP
Code:loadScript( )加载js的功能函数
2007/02/02 Javascript
JSON 编辑器实现代码
2009/12/06 Javascript
Jquery练习之表单验证实现代码
2010/12/14 Javascript
子页向父页传值示例
2013/11/27 Javascript
js对象转json数组的简单实现案例
2014/02/28 Javascript
JavaScript中数据结构与算法(二):队列
2015/06/19 Javascript
关于动态执行代码(js的Eval)实例详解
2016/08/15 Javascript
WEB 前端开发中防治重复提交的实现方法
2016/10/26 Javascript
js获取地址栏中传递的参数(两种方法)
2017/02/08 Javascript
ES6中的箭头函数实例详解
2017/04/06 Javascript
jQuery树插件zTree使用方法详解
2017/05/02 jQuery
JsonProperty 的使用方法详解
2019/10/11 Javascript
[03:40]DOTA2英雄梦之声_第01期_炼金术士
2014/06/23 DOTA
[02:02:38]VG vs Mineski Supermajor 败者组 BO3 第一场 6.6
2018/06/07 DOTA
[37:47]IG vs Winstrike 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
最大K个数问题的Python版解法总结
2016/06/16 Python
Python中functools模块函数解析
2017/03/12 Python
python+matplotlib绘制简单的海豚(顶点和节点的操作)
2018/01/02 Python
利用nohup来开启python文件的方法
2019/01/14 Python
python 实现图片上传接口开发 并生成可以访问的图片url
2019/12/18 Python
双向RNN:bidirectional_dynamic_rnn()函数的使用详解
2020/01/20 Python
Jupyter 无法下载文件夹如何实现曲线救国
2020/04/22 Python
利用Opencv实现图片的油画特效实例
2021/02/28 Python
给海归自荐信的建议
2013/12/13 职场文书
大学生创业项目方案
2014/03/08 职场文书
灰雀教学反思
2014/04/28 职场文书
中秋节活动总结
2014/08/29 职场文书
银行求职信范文怎么写
2015/03/20 职场文书
莫言诺贝尔获奖感言(全文)
2015/07/31 职场文书
《认识年月日》教学反思
2016/02/19 职场文书
浅谈Python类的单继承相关知识
2021/05/12 Python