Python3 面向对象之:多继承
多继承

class ShenXian: # 神仙
def fei(self):
print("神仙都会⻜")
class Monkey: # 猴
def chitao(self):
print("猴⼦喜欢吃桃⼦")
class SunWukong(ShenXian, Monkey): # 孙悟空是神仙, 同时也是⼀只猴
pass
sxz = SunWukong() # 孙悟空
sxz.chitao() # 会吃桃⼦
sxz.fei() # 会⻜

此时, 孙悟空是⼀只猴⼦, 同时也是⼀个神仙. 那孙悟空继承了这两个类. 孙悟空⾃然就可以执⾏这两个类中的⽅法. 多继承⽤起来简单. 也很好理解. 但是多继承中, 存在着这样⼀个问题. 当两个⽗类中出现了重名⽅法的时候. 这时该怎么办呢? 这时就涉及到如何查找⽗类⽅法的这么⼀个问题.即MRO(method resolution order) 问题. 在python中这是⼀个很复杂的问题. 因为在不同的python版本中使⽤的是不同的算法来完成MRO的.
这里需要补充一下python中类的种类(继承需要):
在python2x版本中存在两种类.:
⼀个叫经典类. 在python2.2之前. ⼀直使⽤的是经典类. 经典类在基类的根如果什么都不写.
⼀个叫新式类. 在python2.2之后出现了新式类. 新式类的特点是基类的根是object类。
python3x版本中只有一种类:
python3中使⽤的都是新式类. 如果基类谁都不继承. 那这个类会默认继承 object
1经典类的多继承
虽然在python3中已经不存在经典类了. 但是经典类的MRO最好还是学⼀学. 这是⼀种树形结构遍历的⼀个最直接的案例. 在python的继承体系中. 我们可以把类与类继承关系化成⼀个树形结构的图. 来, 上代码:
代码示例
对付这种mro画图就可以:
继承关系图已经有了. 那如何进⾏查找呢? 记住⼀个原则. 在经典类中采⽤的是深度优先,遍历⽅案. 什么是深度优先. 就是⼀条路走到头. 然后再回来. 继续找下⼀个.
图中每个圈都是准备要送鸡蛋的住址. 箭头和⿊线表⽰线路. 那送鸡蛋的顺序告诉你入⼝在最下⾯R. 并且必须从左往右送. 那怎么送呢?
如图. 肯定是按照123456这样的顺序来送. 那这样的顺序就叫深度优先遍历. ⽽如果是142356呢? 这种被称为⼴度优先遍历. 好了. 深度优先就说这么多. 那么上⾯那个图怎么找的呢? MRO是什么呢? 很简单. 记住. 从头开始. 从左往右. ⼀条路跑到头, 然后回头. 继续⼀条路跑到头. 就是经典类的MRO算法.
类的MRO: Foo-> H -> G -> F -> E -> D -> B -> A -> C. 你猜对了么?
2新式类的多继承
2.1 mro序列
MRO是一个有序列表L,在类被创建时就计算出来。
通用计算公式为:
mro(Child(Base1,Base2)) = [ Child ] + merge( mro(Base1), mro(Base2), [ Base1, Base2] )
(其中Child继承自Base1, Base2)
如果继承至一个基类: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算法的核心。
2.2. 表头和表尾
表头:
列表的第一个元素
表尾:
列表中表头以外的元素集合(可以为空)
示例
列表:[A, B, C]
表头是A,表尾是B和C
2.3. 列表之间的+操作
+操作:
[A] + [B] = [A, B]
(以下的计算中默认省略)
---------------------
merge操作示例:

如计算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操作 ......
---------------------

计算mro(A)方式:

mro(A) = mro( A(B,C) ) 原式= [A] + merge( mro(B),mro(C),[B,C] ) mro(B) = mro( B(D,E) )
= [B] + merge( mro(D), mro(E), [D,E] ) # 多继承
= [B] + merge( [D,O] , [E,O] , [D,E] ) # 单继承mro(D(O))=[D,O]
= [B,D] + merge( [O] , [E,O] , [E] ) # 拿出并删除D
= [B,D,E] + merge([O] , [O])
= [B,D,E,O] mro(C) = mro( C(E,F) )
= [C] + merge( mro(E), mro(F), [E,F] )
= [C] + merge( [E,O] , [F,O] , [E,F] )
= [C,E] + merge( [O] , [F,O] , [F] ) # 跳过O,拿出并删除
= [C,E,F] + merge([O] , [O])
= [C,E,F,O] 原式= [A] + merge( [B,D,E,O], [C,E,F,O], [B,C])
= [A,B] + merge( [D,E,O], [C,E,F,O], [C])
= [A,B,D] + merge( [E,O], [C,E,F,O], [C]) # 跳过E
= [A,B,D,C] + merge([E,O], [E,F,O])
= [A,B,D,C,E] + merge([O], [F,O]) # 跳过O
= [A,B,D,C,E,F] + merge([O], [O])
= [A,B,D,C,E,F,O]
---------------------

结果OK. 那既然python提供了. 为什么我们还要如此⿇烦的计算MRO呢? 因为笔
试.......你在笔试的时候, 是没有电脑的. 所以这个算法要知道. 并且简单的计算要会. 真是项⽬
开发的时候很少有⼈这么去写代码.
这个说完了. 那C3到底怎么看更容易呢? 其实很简单. C3是把我们多个类产⽣的共同继
承留到最后去找. 所以. 我们也可以从图上来看到相关的规律. 这个要⼤家⾃⼰多写多画图就
能感觉到了. 但是如果没有所谓的共同继承关系. 那⼏乎就当成是深度遍历就可以了
Python3 面向对象之:多继承的更多相关文章
- Python3 面向对象-类的继承与派生
1.什么是继承? 继承是一种创建新类的方式,新建的类可以继承一个或多个父类(python支持多继承),父类可称为基类或超类,新建的类称为派生类和或子类. 子类会遗传父类的属性,从而解决代码重用问题. ...
- Python3 与 C# 面向对象之~继承与多态 Python3 与 C# 面向对象之~封装 Python3 与 NetCore 基础语法对比(Function专栏) [C#]C#时间日期操作 [C#]C#中字符串的操作 [ASP.NET]NTKO插件使用常见问题 我对C#的认知。
Python3 与 C# 面向对象之-继承与多态 文章汇总:https://www.cnblogs.com/dotnetcrazy/p/9160514.html 目录: 2.继承 ¶ 2.1.单继 ...
- Python3 面向对象之:单继承
一:什么面向对象的继承? 比较官方的说法就是: 继承(英语:inheritance)是面向对象软件技术当中的一个概念.如果一个类别A“继承自”另一个类别B,就把这个A称为“B的子类别”,而把B称为“A ...
- Python3 面向对象(1)
面向.概述 面向过程: 根据业务逻辑从上到下写垒代码面向过程的设计的核心是过程,过程即解决问题的步骤, 面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西 优点: 极大降低了程序的 ...
- Python面向对象之类的继承(2)
1.除了封装,Python面向对象还有继承这一功能,如下代码,这是简单的继承功能. class Animal: def chi(self): print(self.name+' 吃') def he( ...
- python022 Python3 面向对象
Python3 面向对象 Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的.本章节我们将详细介绍Python的面向对象编程. 如果你以前没有接触 ...
- Python面向对象三要素-继承(Inheritance)
Python面向对象三要素-继承(Inheritance) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.继承概述 1>.基本概念 前面我们学习了Python的面向对象三 ...
- Python面向对象中的继承、多态和封装
Python面向对象中的继承.多态和封装 一.面向对象的三大特性 封装:把很多数据封装到⼀个对象中,把固定功能的代码封装到⼀个代码块, 函数,对象, 打包成模块. 这都属于封装思想. 继承:⼦类可以⾃ ...
- Lua面向对象----类、继承、多继承、单例的实现
(本文转载)学习之用,侵权立删! 原文地址 http://blog.csdn.net/y_23k_bug/article/details/19965877?utm_source=tuicool&a ...
- [.net 面向对象编程基础] (12) 面向对象三大特性——继承
[.net 面向对象编程基础] (12) 面向对象三大特性——继承 上节我们说了面向对象的三大特性之一的封装,解决了将对同一对象所能操作的所有信息放在一起,实现统一对外调用,实现了同一对象的复用,降低 ...
随机推荐
- 12款优秀的 JavaScript 日历和时间选择控件
这些插件能够帮助 Web 开发人员更快速的实现各种精美的日历和时间选择效果. 1. The Coolest Calendar 界面非常漂亮的一款日期选择插件,有详细的使用文档,最新版本 1.5. 点 ...
- jsonp和callback的使用
这两天用 Jquery 跨域取数据的时候,经常碰到 invalid label 这个错误,十分的郁闷,老是取不到服务器端发送回来的 json 值, 一般跨域用到的两个方法为:$.ajax 和$.get ...
- 使用httpclient必须知道的参数设置及代码写法、存在的风险
转发地址:http://jinnianshilongnian.iteye.com/blog/2089792 结论: 如果使用httpclient 3.1并发量比较大的项目,最好升级到httpclien ...
- [LC] 246. Strobogrammatic Number
A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside ...
- Python---8函数(函数的参数&递归函数)
一.函数的参数 Python的函数定义非常简单,但灵活度却非常大.除了正常定义的必选参数外,还可以使用默认参数.可变参数和关键字参数,使得函数定义出来的接口,不但能处理复杂的参数,还可以简化调用者的代 ...
- Painter
时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 杂货店出售一种由N(3<=N<=12)种不同颜色的颜料,每种一瓶(50ML),组成的颜料套装. 你现在需要使用这 ...
- 杂记:OSX 安装openssl
因为工作中要用到openssl中提供的MD5.SHA等摘要算法,通过brew install openssl安装的openssl在C文件中找不到相应的头文件.按照网上的教程各种修改之后还是找不到相应的 ...
- 如何安装及使用honmaple社区程序 · honmaple's blog · 风落花语风落天,花落风雨花落田.
Table of Contents 1. 如何安装及使用 1.1. 安装需要的package 1.2. 配置config 1.3. 注释下面代码 1.4. 初始化数据库 1.5. 创建管理员账户 2. ...
- SetTimeout()多次运行函数后越来越快的问题
问题原因很简单,但是由于代码逻辑问题,一直没有考虑到: 网上有个帖子说的很明白:原帖入口 假如你在0时刻点击了一下按钮,那么500ms时数字会跳一下,1000ms会再跳一下,依次类推,1500,200 ...
- Alberto Del Bimbo:为什么说研究员要有想象力?
Del Bimbo:为什么说研究员要有想象力?" title="Alberto Del Bimbo:为什么说研究员要有想象力?"> 说到科研,与日本式的&q ...