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 相关文章推荐
pycharm 使用心得(四)显示行号
Jun 05 Python
Eclipse中Python开发环境搭建简单教程
Mar 23 Python
VScode编写第一个Python程序HelloWorld步骤
Apr 06 Python
python pandas dataframe 行列选择,切片操作方法
Apr 10 Python
python 定时器,轮询定时器的实例
Feb 20 Python
numpy 声明空数组详解
Dec 05 Python
python ftplib模块使用代码实例
Dec 31 Python
Python爬虫爬取、解析数据操作示例
Mar 27 Python
使用OpenCV获取图片连通域数量,并用不同颜色标记函
Jun 04 Python
如何在Python3中使用telnetlib模块连接网络设备
Sep 21 Python
如何基于python实现年会抽奖工具
Oct 20 Python
Python使用DFA算法过滤内容敏感词
Apr 22 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 多个submit提交表单 处理方法
2009/07/07 PHP
PHP编程函数安全篇
2013/01/08 PHP
CI框架中cookie的操作方法分析
2014/12/12 PHP
PHP SPL 被遗落的宝石【SPL应用浅析】
2018/04/20 PHP
PhpStorm连接服务器并实现自动上传功能
2020/12/09 PHP
JQuery的Validation插件中Remote验证的中文问题
2010/07/26 Javascript
javascript object array方法使用详解
2012/12/03 Javascript
基于jQuery.Validate验证库知识点的详解
2013/04/26 Javascript
js完美解决IE6不支持position:fixed的bug
2015/04/24 Javascript
javascript实现网页字符定位的方法
2015/07/14 Javascript
JavaScript实现为input与textarea自定义hover,focus效果的方法
2015/08/21 Javascript
jQuery实现图片预加载效果
2015/11/27 Javascript
浅谈javascript中的constructor
2016/06/08 Javascript
如何在 Vue.js 中使用第三方js库
2017/04/25 Javascript
BootStrap实现文件上传并带有进度条效果
2017/09/11 Javascript
VuePress 静态网站生成方法步骤
2019/02/14 Javascript
微信小程序表单验证WxValidate的使用
2019/11/27 Javascript
Vue组件简易模拟实现购物车
2020/12/21 Vue.js
[02:10]2018DOTA2亚洲邀请赛赛前采访-Liquid
2018/04/03 DOTA
[00:29]2019完美世界全国高校联赛(秋季赛)总决赛海口落幕
2019/12/10 DOTA
python实现给微信公众号发送消息的方法
2017/06/30 Python
Python编程之序列操作实例详解
2017/07/22 Python
python交互界面的退出方法
2019/02/16 Python
Python爬虫实现爬取百度百科词条功能实例
2019/04/05 Python
Django基础知识 web框架的本质详解
2019/07/18 Python
python实现抠图给证件照换背景源码
2019/08/20 Python
Oracle性能调优原则
2012/05/03 面试题
通用C#笔试题附答案
2016/11/26 面试题
消防先进事迹材料
2014/02/10 职场文书
国庆节慰问信
2015/02/15 职场文书
2015学习委员工作总结范文
2015/04/03 职场文书
摩登时代观后感
2015/06/03 职场文书
担保书格式范文
2015/09/22 职场文书
志愿者服务宣传标语口号
2015/12/26 职场文书
vue-cropper组件实现图片切割上传
2021/05/27 Vue.js
vue中利用mqtt服务端实现即时通讯的步骤记录
2021/07/01 Vue.js