多继承、经典类与新式类、新式类的C3算法详解
多继承Python2版本class A(object) ---> 新式类class B ---> 经典类 Python3版本默认都是新式类 经典类和新式类的不同在于多继承时继承的顺序不同经典类 ---> 深度优先新式类 ---> c3算法
class Immortal:def __init__(self):self.age = "长生不老"def fly(self):print("神仙都会飞")def eat(self):print("神仙也要吃东西")class Monkey:def climb(self):print("猴子都会爬树")def eat(self):print("猴子也要进食")class Monkey_sun(Immortal, Monkey):passsun = Monkey_sun() sun.fly() # 神仙都会飞 sun.climb() # 猴子都会爬树 sun.eat() # 神仙也要吃东西 # --->先计算Monkey_sun(Immortal, Monkey)中最左边的父类
# 前提是Python2版本# 经典类的多继承 class A:pass class B(A):pass class C(A):pass class D(B, C):pass class E:pass class F(D, E):pass class G(F, D):pass class H:pass class Foo(H, G):pass# 深度优先,从左到右,一条路走到底
继承关系图已经有了. 那如何进⾏查找呢? 记住⼀个原则. 在经典类中采⽤的是深度优先,遍历⽅案. 什么是深度优先. 就是⼀条路走到头. 然后再回来. 继续找下⼀个.
如图看出是按照123456这样的顺序来送. 这就叫深度优先遍历.
所以上面Python2版本中的多继承的顺序为:
类的MRO: Foo-> H -> G -> F -> E -> D -> B -> A -> C.
# 新式类的多继承 # mro序列 # MRO是一个有序列表L,在类被创建时就计算出来。# 通用计算公式为: # mro(Child(Base1,Base2)) = [ Child ] + merge( mro(Base1), # mro(Base2), [ Base1, Base2] )(其中Child继承自Base1, Base2)class A:passclass B:passclass C(B, A):pass# mro(C) = mro(C(B, A)) = [C] + merge(mro(A), mro(B), [B, A])
如果继承至一个基类:class B(A)这时B的mro序列为: mro( B ) = mro( B(A) )= [B] + merge( mro(A) + [A] )= [B] + merge( [A] + [A] )= [B,A] 如果继承至多个基类:class B(A1, A2, A3 …)这时B的mro序列 mro(B) = mro( B(A1, A2, A3 …) )= [B] + merge( mro(A1), mro(A2), mro(A3) ..., [A1, A2, A3] )= ... 计算结果为列表,列表中至少有一个元素即类自己如上述示例[A1,A2,A3]。merge操作是C3算法的核心。 表头和表尾表头: 列表的第一个元素 表尾: 列表中表头以外的元素集合(可以为空) 示例 列表:[A, B, C] 表头是A,表尾是B和C 如计算merge( [E,O], [C,E,F,O], [C] )有三个列表 : ① ② ③ 1 merge不为空,取出第一个列表列表①的表头E,进行判断各个列表的表尾分别是[O], [E,F,O],E在这些表尾的集合中,因而跳过当前当前列表2 取出列表②的表头C,进行判断C不在各个列表的集合中,因而将C拿出到merge外,并从所有表头删除merge( [E,O], [C,E,F,O], [C]) = [C] + merge( [E,O], [E,F,O] )3 进行下一次新的merge操作 ......
举例:
# 上面的字母代表类 # 那么,整个多继承关系相当于下面class O:passclass D(O):passclass E(O):passclass F(O):passclass B(D,E):passclass C(E,F):passclass A(B, C):passobj = A() # 这里假设每个类中都有一个 func(),现在要算继承顺序
下面是详细推导过程
1. 首先列出 mor 等式 (最开始,类A继承了类B和类C)
mro(A(B,C)) = [A] + merge(mro(B),mro(C),[B,C])
2. 写出 mor(B)的结果(看上面的图)
mro(B) = mro(B(D,E))---> 类B继承了类D和类E
3. 写出 mor(B(D,E)) 的等式
mro(B(D,E)) = [B] + merge(mro(D),mro(E),[D,E])
4. 把 mor(D) 和 mor(E) 的结果写出来
因为类D和类E都只继承一个类O,所以一下就能得出结果
mro(B(D,E)) = [B] + merge([D,O],[E,O],[D,E])
5. 现在开始推导 merge([D,O],[E,O],[D,E]) 的结果
首先,有三个列表,把第一个列表的表头即D取出来,
把剩下的两个列表的表头也去掉,还剩 [O] [O] [E],
这三个列表中都没有D,因此把D加到[B],然后把列表中有D的去掉D
mro(B(D,E)) = [B,D] + merge([O],[E,O],[E])
6. 推导merge([O],[E,O],[E]),把第一个列表的表头O提出来,
三个列表还剩下 [] [O] [], 第二个列表中有O,跳过,
从 ([O],[E,O],[E]) 第二个列表开始推导,把E提出来,
三个列表还剩下 [] [O] [],都没有E,因此把E加到[B,D]
另外,把所有列表中有E的去掉
mro(B(D,E)) = [B,D,E] + merge([O],[O])
7. 剩下[O],[O]结果就直接是O了,因此最后结果如下所示
mro(B(D,E)) = [B,D,E,O]
8. 按照上面方法推导mro(C) = mro(C(E,F)),过程如下:
mro(C) = mro(C(E,F))
mro(C(E,F)) = [C] + merge([E,O],[F,O],[E,F])
mro(C(E,F)) = [C,E] + merge([O],[F,O],[F])
mro(C(E,F)) = [C,E,F] + merge([O],[O])
mro(C(E,F)) = [C,E,F,O]
9. 接下来算总的,方法一样
mro(A(B,C)) = [A] + merge([B,D,E,O],[C,E,F,O],[B,C])
mro(A(B,C)) = [A,B] + merge([D,E,O],[C,E,F,O],[C])
mro(A(B,C)) = [A,B,D] + merge([E,O],[C,E,F,O],[C])
mro(A(B,C)) = [A,B,D,C] + merge([E,O],[E,F,O])
mro(A(B,C)) = [A,B,D,C,E] + merge([O],[F,O])
mro(A(B,C)) = [A,B,D,C,E,F] + merge([O],[O])
mro(A(B,C)) = [A,B,D,C,E,F,O] ---> 最终结果
上面结果即是新式类的继承顺序
# 对于继承中的 super来说,也一样 # super 也遵循 mro 顺序class O:def func(self):print('in O')class D(O):# passdef func(self):print('in D')class E(O):# passdef func(self):print('in E')class F(O):def func(self):print('in F')class B(D,E):# passdef func(self):print('in B')class C(E,F):# passdef func(self):print('in C')class A(B,C):def func(self):super().func()print('in A')obj = A() obj.func() # in B # in A# mro(A(B,C)) = [A,B,D,C,E,F,O] # 根据上面的结果,如果把类B的 func() 注释掉,即结果变为 # in D # in A# 同理,再把类D的 func() 注释,则结果变为 # in C # in A# 依次类推,因此,super 也遵循 mro 顺序# 当然,真正做项目时可以直接调用 __mro__ 方法来查询顺序 print(A.__mro__) # (<class '__main__.A'>, <class '__main__.B'>, # <class '__main__.D'>, <class '__main__.C'>, # <class '__main__.E'>, <class '__main__.F'>, # <class '__main__.O'>, <class 'object'>)
转载于:https://www.cnblogs.com/shawnhuang/p/10278457.html
多继承、经典类与新式类、新式类的C3算法详解相关推荐
- 中科大-计算机类考研真题(初试笔试真题详解+复试笔试机试真题详解+面试问题汇总分析)
中科大-计算机类考研真题(初试笔试真题详解+复试笔试机试真题详解+面试问题汇总分析) 初试笔试真题2003年~2019年:答案+详解 复试面试问题总结:问题汇总+详解分析 复试面试经验总结:个人小结 ...
- 经典算法详解--CART分类决策树、回归树和模型树
Classification And Regression Tree(CART)是一种很重要的机器学习算法,既可以用于创建分类树(Classification Tree),也可以用于创建回归树(Reg ...
- 算法 经典的八大排序算法详解和代码实现
算法 经典的八大排序算法详解和代码实现 排序算法的介绍 排序的分类 算法的时间复杂度 时间频度 示例 图表理解时间复杂度的特点 时间复杂度 常见的时间复杂度 空间复杂度 排序算法的时间复杂度 冒泡排序 ...
- 自然语言处理NLP星空智能对话机器人系列:第21章:基于Bayesian Theory的MRC文本理解基础经典模型算法详解
自然语言处理NLP星空智能对话机器人系列: 第21章:基于Bayesian Theory的MRC文本理解基础经典模型算法详解 1,Bayesian prior在模型训练时候对Weight控制.训练速度 ...
- 十大经典排序算法详解(三)-堆排序,计数排序,桶排序,基数排序
养成习惯,先赞后看!!! 你的点赞与关注真的对我非常有帮助.如果可以的话,动动手指,一键三连吧!!! 十大经典排序算法-堆排序,计数排序,桶排序,基数排序 前言 这是十大经典排序算法详解的最后一篇了. ...
- 十大经典排序算法-桶排序算法详解
十大经典排序算法 十大经典排序算法-冒泡排序算法详解 十大经典排序算法-选择排序算法详解 十大经典排序算法-插入排序算法详解 十大经典排序算法-希尔排序算法详解 十大经典排序算法-快速排序算法详解 十 ...
- 十大经典排序算法-快速排序算法详解
十大经典排序算法 十大经典排序算法-冒泡排序算法详解 十大经典排序算法-选择排序算法详解 十大经典排序算法-插入排序算法详解 十大经典排序算法-希尔排序算法详解 十大经典排序算法-快速排序算法详解 十 ...
- 十大经典排序算法-选择排序算法详解
十大经典排序算法 十大经典排序算法-冒泡排序算法详解 十大经典排序算法-选择排序算法详解 十大经典排序算法-插入排序算法详解 十大经典排序算法-希尔排序算法详解 十大经典排序算法-快速排序算法详解 十 ...
- 十大经典排序算法详解
本文转自 <卢明冬的博客> 文章目录 排序算法的分析和评价 2.十大排序经典算法总览 2.1 排序算法的分类 2.2 排序算法的性能 2.3 各阶复杂度性能对比 2.4 排序算法的初始状态 ...
最新文章
- AOP具体的实现写法
- SQL语句order by两个字段同时排序
- docker容器的标准使用过程_跟我一起学docker(四)--容器的基本操作
- 链接哈希是什么_熊猫人行情:什么是工作量证明机制(POW)
- linux限制普通账号使用sftp,CentOS6.2使用SFTP限制帐号SSH连接
- 【学习笔记】第三章——内存 III(分段存储、段页式存储、分段和分页对比)
- HDU1048 The Hardest Problem Ever
- Oracle入门教程,新手必读
- BDFZOI 数论小结1(筛法、欧拉phi函数)
- Java编写网络爬虫
- 【ML小结14】条件随机场CRF
- QQ输入法用户体验评价
- OpenCore引导配置说明第十二版-基于OpenCore-0.6.5正式版
- 外螺纹对照表_紧固件螺纹直径与螺距对照表
- turn.js (翻页效果)总结
- VS2010中malloc的使用
- linux下libpng库的安装以及使用
- 借助Google搜索找客户和邮箱
- FPGA之SDRAM控制器设计(一)
- java中如何实例化一个接口_「实例化」java之接口实例化 - seo实验室
热门文章
- python-scrapy简单爬虫实现
- ikvm.net简介
- 更新整理本人所有博文中提供的代码与工具(C++,2013.08)
- python列表套着列表_python 列表套列表去重
- linux系统日志_Linux系统学习系列——Linux系统日志管 理(下 )
- php 模板继承原理,模板继承体会
- Java虚拟机(七)——本地方法接口与本地方法栈
- 搭建CentOS7.6容器镜像
- 3-35Pytorch与visdom
- const变量生存周期_CTM期刊 |神经胶质瘤中HOTAIREZH2抑制剂AQB能上调CWF19L1并促进CDK4/6抑制剂帕博西尼对细胞周期的抑制...