多继承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算法详解相关推荐

  1. 中科大-计算机类考研真题(初试笔试真题详解+复试笔试机试真题详解+面试问题汇总分析)

    中科大-计算机类考研真题(初试笔试真题详解+复试笔试机试真题详解+面试问题汇总分析) 初试笔试真题2003年~2019年:答案+详解 复试面试问题总结:问题汇总+详解分析 复试面试经验总结:个人小结 ...

  2. 经典算法详解--CART分类决策树、回归树和模型树

    Classification And Regression Tree(CART)是一种很重要的机器学习算法,既可以用于创建分类树(Classification Tree),也可以用于创建回归树(Reg ...

  3. 算法 经典的八大排序算法详解和代码实现

    算法 经典的八大排序算法详解和代码实现 排序算法的介绍 排序的分类 算法的时间复杂度 时间频度 示例 图表理解时间复杂度的特点 时间复杂度 常见的时间复杂度 空间复杂度 排序算法的时间复杂度 冒泡排序 ...

  4. 自然语言处理NLP星空智能对话机器人系列:第21章:基于Bayesian Theory的MRC文本理解基础经典模型算法详解

    自然语言处理NLP星空智能对话机器人系列: 第21章:基于Bayesian Theory的MRC文本理解基础经典模型算法详解 1,Bayesian prior在模型训练时候对Weight控制.训练速度 ...

  5. 十大经典排序算法详解(三)-堆排序,计数排序,桶排序,基数排序

    养成习惯,先赞后看!!! 你的点赞与关注真的对我非常有帮助.如果可以的话,动动手指,一键三连吧!!! 十大经典排序算法-堆排序,计数排序,桶排序,基数排序 前言 这是十大经典排序算法详解的最后一篇了. ...

  6. 十大经典排序算法-桶排序算法详解

    十大经典排序算法 十大经典排序算法-冒泡排序算法详解 十大经典排序算法-选择排序算法详解 十大经典排序算法-插入排序算法详解 十大经典排序算法-希尔排序算法详解 十大经典排序算法-快速排序算法详解 十 ...

  7. 十大经典排序算法-快速排序算法详解

    十大经典排序算法 十大经典排序算法-冒泡排序算法详解 十大经典排序算法-选择排序算法详解 十大经典排序算法-插入排序算法详解 十大经典排序算法-希尔排序算法详解 十大经典排序算法-快速排序算法详解 十 ...

  8. 十大经典排序算法-选择排序算法详解

    十大经典排序算法 十大经典排序算法-冒泡排序算法详解 十大经典排序算法-选择排序算法详解 十大经典排序算法-插入排序算法详解 十大经典排序算法-希尔排序算法详解 十大经典排序算法-快速排序算法详解 十 ...

  9. 十大经典排序算法详解

    本文转自 <卢明冬的博客> 文章目录 排序算法的分析和评价 2.十大排序经典算法总览 2.1 排序算法的分类 2.2 排序算法的性能 2.3 各阶复杂度性能对比 2.4 排序算法的初始状态 ...

最新文章

  1. AOP具体的实现写法
  2. SQL语句order by两个字段同时排序
  3. docker容器的标准使用过程_跟我一起学docker(四)--容器的基本操作
  4. 链接哈希是什么_熊猫人行情:什么是工作量证明机制(POW)
  5. linux限制普通账号使用sftp,CentOS6.2使用SFTP限制帐号SSH连接
  6. 【学习笔记】第三章——内存 III(分段存储、段页式存储、分段和分页对比)
  7. HDU1048 The Hardest Problem Ever
  8. Oracle入门教程,新手必读
  9. BDFZOI 数论小结1(筛法、欧拉phi函数)
  10. Java编写网络爬虫
  11. 【ML小结14】条件随机场CRF
  12. QQ输入法用户体验评价
  13. OpenCore引导配置说明第十二版-基于OpenCore-0.6.5正式版
  14. 外螺纹对照表_紧固件螺纹直径与螺距对照表
  15. turn.js (翻页效果)总结
  16. VS2010中malloc的使用
  17. linux下libpng库的安装以及使用
  18. 借助Google搜索找客户和邮箱
  19. FPGA之SDRAM控制器设计(一)
  20. java中如何实例化一个接口_「实例化」java之接口实例化 - seo实验室

热门文章

  1. python-scrapy简单爬虫实现
  2. ikvm.net简介
  3. 更新整理本人所有博文中提供的代码与工具(C++,2013.08)
  4. python列表套着列表_python 列表套列表去重
  5. linux系统日志_Linux系统学习系列——Linux系统日志管 理(下 )
  6. php 模板继承原理,模板继承体会
  7. Java虚拟机(七)——本地方法接口与本地方法栈
  8. 搭建CentOS7.6容器镜像
  9. 3-35Pytorch与visdom
  10. const变量生存周期_CTM期刊 |神经胶质瘤中HOTAIREZH2抑制剂AQB能上调CWF19L1并促进CDK4/6抑制剂帕博西尼对细胞周期的抑制...