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学习思维导图(必看篇)
Jun 26 Python
使用Python微信库itchat获得好友和群组已撤回的消息
Jun 24 Python
Python从Excel中读取日期一列的方法
Nov 28 Python
Python list列表中删除多个重复元素操作示例
Feb 27 Python
python多线程同步之文件读写控制
Feb 25 Python
详解如何用python实现一个简单下载器的服务端和客户端
Oct 28 Python
python 利用已有Ner模型进行数据清洗合并代码
Dec 24 Python
通过python实现windows桌面截图代码实例
Jan 17 Python
logging level级别介绍
Feb 21 Python
pycharm 关掉syntax检查操作
Jun 09 Python
Python实现爬取网页中动态加载的数据
Aug 17 Python
Python Selenium操作Cookie的实例方法
Feb 28 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使用parse_url和parse_str解析URL
2015/02/22 PHP
php基于session实现数据库交互的类实例
2015/08/03 PHP
php仿微信红包分配算法的实现方法
2016/05/13 PHP
Ubuntu VPS中wordpress网站打开时提示”建立数据库连接错误”的解决办法
2016/11/03 PHP
PHP对称加密算法(DES/AES)类的实现代码
2017/11/14 PHP
超酷的网页音乐播放器DewPlayer使用方法
2010/12/18 Javascript
输入自动提示搜索提示功能的javascript:sugggestion.js
2013/09/02 Javascript
禁止选中文字兼容IE、Chrome、FF等
2013/09/04 Javascript
javascript验证上传文件的类型限制必须为某些格式
2013/11/14 Javascript
JavaScript中的typeof操作符用法实例
2014/04/05 Javascript
提升PHP安全:8个必须修改的PHP默认配置
2014/11/17 Javascript
使用JS+plupload直接批量上传图片到又拍云
2014/12/01 Javascript
JavaScript针对网页节点的增删改查用法实例
2015/02/02 Javascript
javascript匀速运动实现方法分析
2016/01/08 Javascript
js匿名函数作为函数参数详解
2016/06/01 Javascript
Bootstrap实现input控件失去焦点时验证
2016/08/04 Javascript
Angular2中Bootstrap界面库ng-bootstrap详解
2016/10/18 Javascript
实例介绍JavaScript中多种组合继承
2019/01/20 Javascript
ios中视频的最后一桢问题解决
2019/05/14 Javascript
深入Python函数编程的一些特性
2015/04/13 Python
解决Python出现_warn_unsafe_extraction问题的方法
2016/03/24 Python
基于hashlib模块--加密(详解)
2017/06/21 Python
Python3.x对JSON的一些操作示例
2017/09/01 Python
Python3爬虫学习之将爬取的信息保存到本地的方法详解
2018/12/12 Python
python队列原理及实现方法示例
2019/11/27 Python
Windows下Pycharm远程连接虚拟机中Centos下的Python环境(图文教程详解)
2020/03/19 Python
scrapy框架携带cookie访问淘宝购物车功能的实现代码
2020/07/07 Python
Python代码注释规范代码实例解析
2020/08/14 Python
详解基于Facecognition+Opencv快速搭建人脸识别及跟踪应用
2021/01/21 Python
web字体加载方案优化小结
2019/11/29 HTML / CSS
介绍一下Linux中的链接
2016/06/05 面试题
高中毕业生个人自我鉴定
2013/11/24 职场文书
2014年商场工作总结
2014/11/22 职场文书
教研活动主持词
2015/07/03 职场文书
幼儿园教师管理制度
2015/08/05 职场文书
基于Redission的分布式锁实战
2022/08/14 Redis