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中的random()方法的使用介绍
May 15 Python
Python 异常处理的实例详解
Sep 11 Python
python实现发送邮件功能代码
Dec 14 Python
python实现装饰器、描述符
Feb 28 Python
对python GUI实现完美进度条的示例详解
Dec 13 Python
对python中矩阵相加函数sum()的使用详解
Jan 28 Python
Python字符串对象实现原理详解
Jul 01 Python
Python学习笔记之Zip和Enumerate用法实例分析
Aug 14 Python
如何基于Python制作有道翻译小工具
Dec 16 Python
浅谈keras2 predict和fit_generator的坑
Jun 17 Python
Python中的特殊方法以及应用详解
Sep 20 Python
python中uuid模块实例浅析
Dec 29 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
IIS下配置Php+Mysql+zend的图文教程
2006/12/08 PHP
php5.2时间相差8小时
2007/01/15 PHP
win7计划任务定时执行PHP脚本设置图解
2014/05/09 PHP
PHP 数组黑名单/白名单实例代码详解
2019/06/04 PHP
转自Jquery官方 jQuery1.1.3发布,速度提升800%,体积保持20K
2007/08/19 Javascript
js获取url中的参数且参数为中文时通过js解码
2014/03/19 Javascript
js使用循环清空某个div中的input标签值
2014/09/29 Javascript
iScroll中事件点击触发两次解决方案
2015/03/11 Javascript
EasyUi中的Combogrid 实现分页和动态搜索远程数据
2016/04/01 Javascript
Bootstrap框架结合jQuery仿百度换肤功能实例解析
2016/09/17 Javascript
webpack2.0配置postcss-loader的方法
2017/08/17 Javascript
关于Angularjs中自定义指令一些有价值的细节和技巧小结
2018/04/22 Javascript
Angular学习教程之RouterLink花式跳转
2018/05/03 Javascript
Vue拖拽组件开发实例详解
2018/05/11 Javascript
基于Vue自定义指令实现按钮级权限控制思路详解
2018/05/23 Javascript
详解javascript appendChild()的完整功能
2018/08/18 Javascript
vue如何解决循环引用组件报错的问题
2018/09/22 Javascript
使用vue开发移动端管理后台的注意事项
2019/03/07 Javascript
分享一款超好用的JavaScript 打包压缩工具
2020/04/26 Javascript
Python2.5/2.6实用教程 入门基础篇
2009/11/29 Python
Python压缩解压缩zip文件及破解zip文件密码的方法
2015/11/04 Python
Python中pow()和math.pow()函数用法示例
2018/02/11 Python
python3+PyQt5泛型委托详解
2018/04/24 Python
python 字符串常用方法汇总详解
2019/09/16 Python
Django设置Postgresql的操作
2020/05/14 Python
使用python实现下载我们想听的歌曲,速度超快
2020/07/09 Python
Melijoe时尚童装德国官网:Melijoe德国
2016/09/03 全球购物
周仰杰(JIMMY CHOO)法国官方网站:闻名世界的鞋子品牌
2019/09/27 全球购物
高中生学习生活的自我评价
2013/10/09 职场文书
乡领导班子四风问题对照检查材料
2014/09/25 职场文书
党干部专题民主生活会对照检查材料思想汇报
2014/10/06 职场文书
2014年话务员工作总结
2014/11/19 职场文书
建议书范文
2015/02/05 职场文书
毕业论文答辩开场白和结束语
2015/05/27 职场文书
辅导员学期工作总结
2015/08/14 职场文书
维护民族团结心得体会2016
2016/01/15 职场文书