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实现八大排序算法
Aug 13 Python
Python利用Beautiful Soup模块创建对象详解
Mar 27 Python
Python打印“菱形”星号代码方法
Feb 05 Python
pandas的唯一值、值计数以及成员资格的示例
Jul 25 Python
解决django前后端分离csrf验证的问题
Feb 03 Python
Python动态赋值的陷阱知识点总结
Mar 17 Python
Django Channels 实现点对点实时聊天和消息推送功能
Jul 17 Python
python库matplotlib绘制坐标图
Oct 18 Python
python 检查数据中是否有缺失值,删除缺失值的方式
Dec 02 Python
python生成特定分布数的实例
Dec 05 Python
Python pip配置国内源的方法
Feb 14 Python
Python实现验证码识别
Jun 15 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中ADODB类详解
2008/03/25 PHP
require(),include(),require_once()和include_once()区别
2008/03/27 PHP
用PHP读取超大文件的实例代码
2012/04/01 PHP
再推荐十款免费的php开发工具
2015/11/09 PHP
php session 写入数据库
2016/02/13 PHP
PHP实现基于状态的责任链审批模式详解
2019/05/31 PHP
php + ajax 实现的写入数据库操作简单示例
2020/05/16 PHP
基于ThinkPHP删除目录及目录文件函数
2020/10/28 PHP
javascript 写类方式之三
2009/07/05 Javascript
解决Extjs上传图片无法预览的解决方法
2012/03/22 Javascript
jQuery 1.8 Release版本发布了
2012/08/14 Javascript
如何将网页表格内容导入excel
2014/02/18 Javascript
jquery如何把数组变为字符串传到服务端并处理
2014/04/30 Javascript
js实现浏览器倒计时跳转页面效果
2016/08/12 Javascript
一个有意思的鼠标点击文字特效jquery代码
2017/09/23 jQuery
图片文字识别(OCR)插件Ocrad.js教程
2018/11/26 Javascript
详解为生产环境编译Angular2应用的方法
2018/12/10 Javascript
jsonp实现百度下拉框功能的方法分析
2019/05/10 Javascript
[51:06]2018DOTA2亚洲邀请赛3月29日 小组赛A组 KG VS Liquid
2018/03/30 DOTA
python 输出一个两行字符的变量
2009/02/05 Python
在Python web中实现验证码图片代码分享
2017/11/09 Python
python爬虫之xpath的基本使用详解
2018/04/18 Python
5分钟 Pipenv 上手指南
2018/12/20 Python
决策树剪枝算法的python实现方法详解
2019/09/18 Python
adidas泰国官网:adidas TH
2020/07/11 全球购物
《胖乎乎的小手》教学反思
2014/02/26 职场文书
小班下学期评语
2014/05/04 职场文书
党员干部四风问题整改措施思想汇报
2014/10/12 职场文书
民政局办理协议离婚(范本)
2014/10/25 职场文书
社区党建工作汇报材料
2014/10/27 职场文书
优秀教师申报材料
2014/12/16 职场文书
工作经验交流材料
2014/12/30 职场文书
区域经理岗位职责
2015/02/02 职场文书
电影雷锋观后感
2015/06/10 职场文书
升学宴家长致辞
2015/07/27 职场文书
JavaWeb 入门篇:创建Web项目,Idea配置tomcat
2021/07/16 Java/Android