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(Tornado)模拟登录小米抢手机
Nov 12 Python
在Python中操作列表之List.append()方法的使用
May 20 Python
Python爬虫DOTA排行榜爬取实例(分享)
Jun 13 Python
怎么使用pipenv管理你的python项目
Mar 12 Python
Python操作MySQL模拟银行转账
Mar 12 Python
python 编写简单网页服务器的实例
Jun 01 Python
python3 webp转gif格式的实现示例
Dec 10 Python
Python模块/包/库安装的六种方法及区别
Feb 24 Python
Pytorch十九种损失函数的使用详解
Apr 29 Python
解决Keras TensorFlow 混编中 trainable=False设置无效问题
Jun 28 Python
学会迭代器设计模式,帮你大幅提升python性能
Jan 03 Python
Python列表的索引与切片
Apr 07 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输出时间差函数代码
2013/01/28 PHP
Yii中render和renderPartial的区别
2014/09/03 PHP
php结合正则批量抓取网页中邮箱地址
2015/05/19 PHP
Twig模板引擎用法入门教程
2016/01/20 PHP
PHP使用Redis实现Session共享的实现示例
2019/05/12 PHP
jquery监控数据是否变化(修正版)
2011/04/12 Javascript
JavaScript设计模式之观察者模式(发布者-订阅者模式)
2014/09/24 Javascript
Bootstrap CSS布局之代码
2016/12/17 Javascript
简单理解js的冒泡排序
2016/12/19 Javascript
完美解决UI-Grid表格元素中多个空格显示为一个空格的问题
2017/04/25 Javascript
jQuery ajax调用webservice注意事项
2017/10/08 jQuery
javaScript字符串工具类StringUtils详解
2017/12/08 Javascript
Vue 路由 过渡动效 数据获取方法
2018/07/31 Javascript
vue中子组件传递数据给父组件的讲解
2019/01/27 Javascript
vue2.0+SVG实现音乐播放圆形进度条组件
2019/09/21 Javascript
Vue设置长时间未操作登录自动到期返回登录页
2020/01/22 Javascript
es6数组的flat(),flatMap()函数用法实例分析
2020/04/18 Javascript
Python实现各种排序算法的代码示例总结
2015/12/11 Python
Python+Socket实现基于UDP协议的局域网广播功能示例
2017/08/31 Python
python单例模式获取IP代理的方法详解
2018/09/13 Python
Python matplotlib的使用并自定义colormap的方法
2018/12/13 Python
11个Python3字典内置方法大全与示例汇总
2019/05/13 Python
python安装requests库的实例代码
2019/06/25 Python
Python日志无延迟实时写入的示例
2019/07/11 Python
解决django框架model中外键不落实到数据库问题
2020/05/20 Python
keras.utils.to_categorical和one hot格式解析
2020/07/02 Python
PyCharm+PyQt5+QtDesigner配置详解
2020/08/12 Python
Html5如何唤起百度地图App的方法
2019/01/27 HTML / CSS
澳大利亚百货公司:David Jones
2018/02/08 全球购物
营销专业应届生求职信
2013/11/26 职场文书
毕业生工作求职信
2014/06/30 职场文书
2014年招商引资工作总结
2014/11/22 职场文书
2015年药品销售工作总结范文
2015/05/25 职场文书
六一儿童节园长致辞
2015/07/31 职场文书
大学生奶茶店创业计划书
2019/06/25 职场文书
使用@Value值注入及配置文件组件扫描
2021/07/09 Java/Android