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的Django框架中的ORM建立查询API
Apr 20 Python
TensorFlow 模型载入方法汇总(小结)
Jun 19 Python
浅析python中numpy包中的argsort函数的使用
Aug 30 Python
Python使用Selenium爬取淘宝异步加载的数据方法
Dec 17 Python
介绍一款python类型检查工具pyright(推荐)
Jul 03 Python
python脚本之一键移动自定格式文件方法实例
Sep 02 Python
在keras中获取某一层上的feature map实例
Jan 24 Python
django之导入并执行自定义的函数模块图解
Apr 01 Python
Python logging模块写入中文出现乱码
May 21 Python
python通过cython加密代码
Dec 11 Python
使paramiko库执行命令时在给定的时间强制退出功能的实现
Mar 03 Python
使用Djongo模块在Django中使用MongoDB数据库
Jun 20 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小马小结(方便查找后门的朋友)
2012/05/05 PHP
微信access_token的获取开发示例
2015/04/16 PHP
CodeIgniter记录错误日志的方法全面总结
2016/05/17 PHP
PHP面向对象程序设计组合模式与装饰模式详解
2016/12/02 PHP
php实现微信模板消息推送
2018/03/30 PHP
PHP 实现base64编码文件上传出现问题详解
2020/09/01 PHP
input、button的不同type值在ajax提交表单时导致的陷阱
2009/02/24 Javascript
javascript replace()正则替换实现代码
2010/02/26 Javascript
jtable列中自定义button示例代码
2013/11/21 Javascript
JS通过分析userAgent属性来判断浏览器的类型及版本
2014/03/28 Javascript
javascript 闭包详解
2015/07/02 Javascript
JavaScript中各种引用类型的常用操作方法小结
2016/05/05 Javascript
node+experss实现爬取电影天堂爬虫
2016/11/20 Javascript
jquery UI Datepicker时间控件冲突问题解决
2016/12/16 Javascript
使用AngularJS2中的指令实现按钮的切换效果
2017/03/27 Javascript
js和jquery中获取非行间样式
2017/05/05 jQuery
python遍历 truple list dictionary的几种方法总结
2016/09/11 Python
Python如何读取MySQL数据库表数据
2017/03/11 Python
python flask实现分页效果
2017/06/27 Python
Django 2.0版本的新特性抢先看!
2018/01/05 Python
Python3.4实现远程控制电脑开关机
2018/02/22 Python
python GUI实现小球满屏乱跑效果
2019/05/09 Python
用vue.js组件模拟v-model指令实例方法
2019/07/05 Python
如何使用Python自动控制windows桌面
2019/07/11 Python
详解如何减少python内存的消耗
2019/08/09 Python
Python爬取腾讯视频评论的思路详解
2019/12/19 Python
Python实现自动签到脚本功能
2020/08/20 Python
法国体育用品商店:GO Sport
2019/10/23 全球购物
小学生作文评语
2014/04/18 职场文书
三严三实对照检查材料
2014/08/25 职场文书
“四风”查摆问题自我剖析材料
2014/09/27 职场文书
关于有小孩的离婚协议书
2014/10/26 职场文书
试用期辞职信范文
2015/03/02 职场文书
医务人员岗前培训心得体会
2016/01/08 职场文书
志愿服务心得体会
2016/01/15 职场文书
Golang二维切片初始化的实现
2021/04/08 Golang