Python新式类继承的C3算法
在Python的新式类中,方法解析顺序并非是广度优先的算法,而是采用C3算法,只是在某些情况下,C3算法的结果恰巧符合广度优先算法的结果。
可以通过代码来验证下:
class NewStyleClassA(object):
var = 'New Style Class A' class NewStyleClassB(NewStyleClassA):
pass class NewStyleClassC(NewStyleClassA):
var = 'New Style Class C' class SubNewStyleClass(NewStyleClassB, NewStyleClassC):
pass if __name__ == '__main__':
print(SubNewStyleClass.mro())
print(SubNewStyleClass.var)
从第一段代码的运行结果来看,与广度优先的算法结果恰巧相同,但也只是恰巧相同,不等于就是广度优先的算法。
[<class '__main__.SubNewStyleClass'>, <class '__main__.NewStyleClassB'>, <class '__main__.NewStyleClassC'>, <class '__main__.NewStyleClassA'>, <type 'object'>]
New Style Class C
通过对代码进行修改可以证实:
将NewStyleClassC改为继承自object
class NewStyleClassA(object):
var = 'New Style Class A' class NewStyleClassB(NewStyleClassA):
pass class NewStyleClassC(object):
var = 'New Style Class C' class SubNewStyleClass(NewStyleClassB, NewStyleClassC):
pass if __name__ == '__main__':
print(SubNewStyleClass.mro())
print(SubNewStyleClass.var)
运行代码输出结果
[<class '__main__.SubNewStyleClass'>, <class '__main__.NewStyleClassB'>, <class '__main__.NewStyleClassA'>, <class '__main__.NewStyleClassC'>, <type 'object'>]
New Style Class A
从代码运行结果上看,并不符合广度优先的原则。
关于C3算法,在Python官方文档中是如此解释的:
take the head of the first list, i.e L[B1][0]; if this head is not in the tail of any of the other lists, then add it to the linearization of C and remove it from the lists in the merge, otherwise look at the head of the next list and take it, if it is a good head. Then repeat the operation until all the class are removed or it is impossible to find good heads. In this case, it is impossible to construct the merge, Python 2.3 will refuse to create the class C and will raise an exception.
C3算法的本质就是Merge,不断地把mro()函数返回的序列进行Merge,规则如下:
1. 如果第一个序列的第一个元素,是后续序列的第一个元素,或者不再后续序列中再次出现,则将这个元素合并到最终的方法解析顺序序列中,并从当前操作的全部序列中删除。
2. 如果不符合,则跳过此元素,查找下一个列表的第一个元素,重复1的判断规则
使用第一段代码逐步进行方法解析:
1.先打印NewStyleClassB和NewStyleClassC的mro(),得到他们的继承顺序序列
[<class '__main__.NewStyleClassB'>, <class '__main__.NewStyleClassA'>, <class 'object'>]
[<class '__main__.NewStyleClassC'>, <class 'object'>]
2.根据C3算法逐步对继承顺序进行解析:
mro(SubNewStyleClass)
= [SubNewStyleClass] + merge(mro(NewStyleClassB), mro(NewStyleClassC), [NewStyleClassB, NewStyleClassC])
# 根据第一步的打印结果,可以得出
= [SubNewStyleClass] + merge([NewStyleClassB, NewStyleClassA, object], [NewStyleClassC, NewStyleClassA, object], [NewStyleClassB, NewStyleClassC])
# 判断merge的当前序列第一个元素 NewStyleClassB, 在第三个序列中的第一个元素也存在,所以将其合并到最终序列并且删除:
= [SubNewStyleClass, NewStyleClassB] + merge([NewStyleClassA, object], [NewStyleClassC, NewStyleClassA, object], [NewStyleClassC])
# 判断merge的当前序列第一个元素 NewStyleClassA,在第二个序列中存在,并且不为第二个序列的第一个元素,则跳过
# 继续判断第二个序列中的第一个元素 NewStyleClassC,在第三个序列中存在,并且为第一个元素,所以将其合并到最终序列并且删除:
= [SubNewStyleClass, NewStyleClassB, NewStyleClassC] + merge([NewStyleClassA, object], [NewStyleClassA, object])
# 目前第一个序列的第一个元素是NewStyleClassA,所以再次对NewStyleClassA进行判断。
# NewStyleClassA在第二个序列中存在,并且为第二个序列的第一个元素,所以将其合并到最终序列并且删除:
= [SubNewStyleClass, NewStyleClassB, NewStyleClassC, NewStyleClassA] + merge([object], [object])
# 最终object,在第二个序列中出现,并且为第一个元素,所以将其合并到最终的序列并且删除,得到最终的继承顺序:
= [SubNewStyleClass, NewStyleClassB, NewStyleClassC, NewStyleClassA, object)
解析的结果和调用SubNewStyleClass.mro()方法打印出的结果是相同的:
[<class '__main__.SubNewStyleClass'>, <class '__main__.NewStyleClassB'>, <class '__main__.NewStyleClassC'>, <class '__main__.NewStyleClassA'>, <class 'object'>]
使用第二段代码逐步进行方法解析:
1. 先打印NewStyleClassB和NewStyleClassC的mro(),得到他们的继承顺序序列
[<class '__main__.NewStyleClassB'>, <class '__main__.NewStyleClassA'>, <class 'object'>]
[<class '__main__.NewStyleClassC'>, <class 'object'>]
2. 根据C3算法逐步对继承顺序进行解析:
mro(SubNewStyleClass)
= [SubNewStyleClass] + merge(mro(NewStyleClassB), mro(NewStyleClassC), [NewStyleClassB, NewStyleClassC])
# 根据第一步的打印结果,可以得出
= [SubNewStyleClass] + merge([NewStyleClassB, NewStyleClassA, object], [NewStyleClassC, object], [NewStyleClassB, NewStyleClassC])
# 判断merge的当前序列第一个元素 NewStyleClassB, 在第三个序列中的第一个元素也存在,所以将其合并到最终序列并且删除:
= [SubNewStyleClass, NewStyleClassB] + merge([NewStyleClassA, object], [NewStyleClassC, object], [NewStyleClassC])
# 判断merge的当前序列第一个元素 NewStyleClassA,在后续的序列中都不存在,所以将其合并到最终的序列并且删除:
= [SubNewStyleClass, NewStyleClassB, NewStyleClassA] + merge([object], [NewStyleClassC, object], [NewStyleClassC])
# 判断merge的当前序列第一个元素 object,在第二个序列中出现,并且不是第一个元素,则跳过
# 跳过object后,继续判断下个序列的第一个元素,也就是第二个序列的第一个元素NewStyleClassC,在第三个序列中出现并且为第一个元素,所以将其合并到最终的序列并且删除:
= [SubNewStyleClass, NewStyleClassB, NewStyleClassA, NewStyleClassC] + merge([object], [object])
# 再次判断object,在第二个序列中出现,并且为第一个元素,所以将其合并到最终的序列并且删除,得到最终的继承顺序:
= [SubNewStyleClass, NewStyleClassB, NewStyleClassA, NewStyleClassC, object)
和调用SubNewStyleClass.mro()方法打印出的结果是相同的
[<class '__main__.SubNewStyleClass'>, <class '__main__.NewStyleClassB'>, <class '__main__.NewStyleClassA'>, <class '__main__.NewStyleClassC'>, <class 'object'>]
Python新式类继承的C3算法的更多相关文章
- python新式类继承------C3算法
一.引入 mro即method resolution order,主要用于在多继承时判断调的属性的路径(来自于哪个类).之前查看了很多资料,说mro是基于深度优先搜索算法的.但不完全正确在Python ...
- Python之从继承到C3算法
在Python2.X和Python3.X有很多不同的地方,其中一个区别就是和继承有关. 在Python3.X中,一个类如果没有指明其继承哪个类的时候,其默认就是继承object类. 而在Python2 ...
- python中的MRO和C3算法
一. 经典类和新式类 1.python多继承 在继承关系中,python子类自动用友父类中除了私有属性外的其他所有内容.python支持多继承.一个类可以拥有多个父类 2.python2和python ...
- Python新式类和经典类的区别
@Python新式类和经典类的区别 class ClassicClass(): pass class NewStyleClass(object): pass x1 = ClassicClass() x ...
- 类的继承和C3算法
在Python的新式类中,方法解析顺序并非是广度优先的算法,而是采用C3算法,只是在某些情况下,C3算法的结果恰巧符合广度优先算法的结果. 可以通过代码来验证下: class NewStyleClas ...
- Python多继承的C3算法
C3算法 一.知识点补充: 拓扑排序:在图论中,拓扑排序(Topological Sorting) 是一个 有向无环图(DAG,Directed Acyclic Graph) 的所有顶点的线性序列.且 ...
- Python新式类与经典类的区别
1.新式类与经典类 在Python 2及以前的版本中,由任意内置类型派生出的类(只要一个内置类型位于类树的某个位置),都属于“新式类”,都会获得所有“新式类”的特性:反之,即不由任意内置类型派生出的类 ...
- Python新式类与经典类(旧式类)的区别
看写poc的时候看到的,思考了半天,现在解决了 转载自http://blog.csdn.net/zimou5581/article/details/53053775 Python中类分两种:旧式类和新 ...
- python之路--MRO和C3算法
一 . MRO(method resolution order) 多继承的一种方法,一种查找的顺序 在python3 里面是一种新类式MRO 需要用都的是C3算法 class A: pass clas ...
随机推荐
- javascript设计模式——职责链模式
前面的话 职责链模式的定义是使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止.职责链模式的名字非常形象,一 ...
- HDU 4556 Stern-Brocot Tree
题意:求SB树第N层分母分子小于均等于N的数有多少? 搞清楚了SB Tree的性质,这道题就很容易了.因为SB Tree中的数均为最简分数,所以筛一波欧拉函数即可. #include<bits/ ...
- springBoot数据库连接池常用配置
在配置文件中添加配置如下(我使用的是多数据源): spring.datasource.primary.url=jdbc\:mysql\://localhost\:3306/test?useUnicod ...
- java日期详解
[TOC] 一.简介 java中的日期处理一直是个问题,没有很好的方式去处理,所以才有第三方框架的地位比如joda. 文章主要对java日期处理的详解,用1.8可以不用joda. 1. 相关概念 首先 ...
- webrtc视频数据接收端处理流程详解
- JAVA基础-----Maven项目的搭建
Maven项目的搭建 一.前言 maven官网:http://maven.apache.org/, 文章简介:本文章从三个模块来了解Maven,分别是 Maven的基本概念~, Maven项目的安装和 ...
- UILabel 的使用
直接上代码: /* UILabel 使用 */ UILabel *aLable = [[UILabel alloc] initWithFrame:self.window.bounds]; aLable ...
- OC对象与Core Foundation对象的转换
OC对象使用了ARC,自己主动释放内存,可是CF中的对象没有ARC,必需要手动进行引用计数和内存释放. 两者对象之间的互相转换有三种形式: 1.__bridge: 直接转换,部改变对象的持有状况: i ...
- 如何导入外部的源码到eclipse中
用struts,spring等框架开发也有两年的时间了,一直很少去阅读其源码,每次在eclipse编码的过程中想要看某一个类的源码,ctrl点击总是出现source not found的提示,也没有去 ...
- json的那些事
1.什么是json? json(javascript object notation)全称是javascript对象表示法,它是一种数据交换的文本格式,而不是一种编程语言,用于读取结构化数据.简单来说 ...