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追加元素到列表的方法
Jul 28 Python
Python的Tornado框架实现异步非阻塞访问数据库的示例
Jun 30 Python
Python3之读取连接过的网络并定位的方法
Apr 22 Python
pyhanlp安装介绍和简单应用
Feb 22 Python
六行python代码的爱心曲线详解
May 17 Python
python可视化爬虫界面之天气查询
Jul 03 Python
django实现HttpResponse返回json数据为中文
Mar 27 Python
python 删除excel表格重复行,数据预处理操作
Jul 06 Python
python设置表格边框的具体方法
Jul 17 Python
详解Pycharm与anaconda安装配置指南
Aug 25 Python
在pycharm中无法import所安装的库解决方案
May 31 Python
Python访问Redis的详细操作
Jun 26 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
Terran兵种介绍
2020/03/14 星际争霸
基于mysql的bbs设计(三)
2006/10/09 PHP
php与java通过socket通信的实现代码
2013/10/21 PHP
Laravel学习教程之model validation的使用示例
2017/10/23 PHP
Mootools 1.2教程 同时进行多个形变动画
2009/09/15 Javascript
轻轻松松学JS调试(不下载任何工具)
2010/04/14 Javascript
利用javascript的面向对象的特性实现限制试用期
2011/08/04 Javascript
仿jQuery的siblings效果的js代码
2011/08/09 Javascript
js动态生成指定行数的表格
2013/07/11 Javascript
简单谈谈Vue 模板各类数据绑定
2016/09/25 Javascript
浅谈Webpack 是如何加载模块的
2018/05/24 Javascript
微信小程序时间控件picker view使用详解
2018/12/28 Javascript
记录微信小程序 height: calc(xx - xx);无效问题
2019/12/30 Javascript
JS XMLHttpRequest原理与使用方法深入详解
2020/04/30 Javascript
JS字符串和数组如何实现相互转化
2020/07/02 Javascript
Vue实现图书管理案例
2021/01/20 Vue.js
[01:01:18]VP vs NIP 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
python实现在windows服务中新建进程的方法
2015/06/30 Python
K-means聚类算法介绍与利用python实现的代码示例
2017/11/13 Python
Python实现的用户登录系统功能示例
2018/02/05 Python
基于随机梯度下降的矩阵分解推荐算法(python)
2018/08/31 Python
在Python中调用Ping命令,批量IP的方法
2019/01/26 Python
在linux系统下安装python librtmp包的实现方法
2019/07/22 Python
python numpy之np.random的随机数函数使用介绍
2019/10/06 Python
Python 、Pycharm、Anaconda三者的区别与联系、安装过程及注意事项
2019/10/11 Python
PyCharm 2020.2 安装详细教程
2020/09/25 Python
Python+pyftpdlib实现局域网文件互传
2020/08/24 Python
香蕉共和国Banana Republic官网:美国GAP旗下偏贵族风格服饰品牌
2016/11/21 全球购物
Mankind美国/加拿大:英国领先的男士美容护发用品公司
2018/12/05 全球购物
Timberland德国官网:靴子、鞋子、衣服、夹克及配件
2019/12/10 全球购物
岗位竞聘演讲稿范文
2014/04/24 职场文书
公共场所禁烟标语
2014/06/25 职场文书
2015年党员自评材料
2014/12/17 职场文书
如何用python插入独创性声明
2021/03/31 Python
JUnit5常用注解的使用
2021/07/02 Java/Android
Java GUI编程菜单组件实例详解
2022/04/07 Java/Android