继承是面向对象编程的一个重要的方式,通过继承,子类就可以扩展父类的功能。在python中一个类能继承自不止一个父类,这叫做python的多重继承(Multiple Inheritance )。

语法

class SubclassName(BaseClass1, BaseClass2, BaseClass3, ...):
pass

菱形继承

在多层继承和多继承同时使用的情况下,就会出现复杂的继承关系,多重多继承。

其中,就会出现菱形继承。如下图所示。

在这种结构中,在调用顺序上就出现了疑惑,调用顺序究竟是以下哪一种顺序呢

  • D->B->A->C(深度优先)
  • D->B->C->A(广度优先)

下面我们来解答下这个问题。

举个例子来看下:

class A():
def __init__(self):
print('init A...')
print('end A...') class B(A):
def __init__(self):
print('init B...')
A.__init__(self)
print('end B...') class C(A):
def __init__(self):
print('init C...')
A.__init__(self)
print('end C...') class D(B, C):
def __init__(self):
print('init D...')
B.__init__(self)
C.__init__(self)
print('end D...') if __name__ == '__main__':
D()

输出结果

init D...
init B...
init A...
end A...
end B...
init C...
init A...
end A...
end C...
end D...

从输出结果中看,调用顺序为:D->B->A->C->A。可以看到,B、C共同继承于A,A被调用了两次。A没必要重复调用两次。

其实,上面问题的根源都跟MRO有关,MRO(Method Resolution Order)也叫方法解析顺序,主要用于在多重继承时判断调的属性来自于哪个类,其使用了一种叫做C3的算法,其基本思想时在避免同一类被调用多次的前提下,使用广度优先和从左到右的原则去寻找需要的属性和方法。

那么如何避免顶层父类中的某个方法被多次调用呢,此时就需要super()来发挥作用了,super本质上是一个类,内部记录着MRO信息,由于C3算法确保同一个类只会被搜寻一次,这样就避免了顶层父类中的方法被多次执行了,上面代码可以改为:

class A():
def __init__(self):
print('init A...')
print('end A...') class B(A):
def __init__(self):
print('init B...')
super(B, self).__init__()
print('end B...') class C(A):
def __init__(self):
print('init C...')
super(C, self).__init__()
print('end C...') class D(B, C):
def __init__(self):
print('init D...')
super(D, self).__init__()
print('end D...') if __name__ == '__main__':
D()

输出结果:

init D...
init B...
init C...
init A...
end A...
end C...
end B...
end D...

可以看出,此时的调用顺序是D->B->C->A。即采用是广度优先的遍历方式。

补充内容

Python类分为两种,一种叫经典类,一种叫新式类。都支持多继承,但继承顺序不同。

  • 新式类:从object继承来的类。(如:class A(object)),采用广度优先搜索的方式继承(即先水平搜索,再向上搜索)。
  • 经典类:不从object继承来的类。(如:class A()),采用深度优先搜索的方式继承(即先深入继承树的左侧,再返回,再找右侧)。

Python2.x中类的是有经典类和新式类两种。Python3.x中都是新式类。

打开微信扫一扫,关注【西加加先生】微信公众号,及时接收博文推送

Python多重继承之菱形继承的更多相关文章

  1. C++逆向分析----多重继承和菱形继承

    多重继承 多重继承是指C++类同时继承两个类或两个以上的类. class Test { public: int num1; Test() { num1 = 1; } virtual void Proc ...

  2. C++反汇编第五讲,认识多重继承,菱形继承的内存结构,以及反汇编中的表现形式.

    C++反汇编第五讲,认识多重继承,菱形继承的内存结构,以及反汇编中的表现形式. 目录: 1.多重继承在内存中的表现形式 多重继承在汇编中的表现形式 2.菱形继承 普通的菱形继承 虚继承 汇编中的表现形 ...

  3. python 菱形继承问题究极版

    如果只是正常的菱形继承,经典类(python2中最后一个父类不继承object类)是深度优先,即会从左边父类开始一路走到底 新式类(最后一个父类继承了object类)是广度优先,即从左边父类开始继承, ...

  4. Python面向对象(组合、菱形继承、多态)

    今日内容: 1.组合 2.菱形继承 3.多态与多态性 昨天内容重点回顾: 1)调用也叫实例化:发生了2件事  1.创造空对象  2.触发对象下的__init__方法,然后将p连同参数一同传给init  ...

  5. C++反汇编第四讲,认识多重继承,菱形继承的内存结构,以及反汇编中的表现形式.

    目录: 1.多重继承在内存中的表现形式 多重继承在汇编中的表现形式 2.菱形继承 普通的菱形继承 虚继承 汇编中的表现形式 一丶多重继承在内存中的表现形式 高级代码: class Father1 { ...

  6. 028.Python面向对象继承(单继承,多继承,super,菱形继承)

    一 继承的概念 种类 单继承 多继承 至少两个类: 子类:一个类继承另外一个类,那么该类是子类(也叫作衍生类) 父类:另外一个,这个被继承的类,叫做父类(也叫作超类),object 在python中 ...

  7. python基础-面向对象编程之继承

    面向对象编程之继承 继承的定义:是一种新建类的方式,新建的类称之为子类或派生类,被继承的父类称之为基类或超类 继承的作用:子类会""遗传"父类的属性,从而解决代码重用问题 ...

  8. python中使用多继承

    python中使用多继承,会涉及到查找顺序(MRO).重复调用(钻石继承,也叫菱形继承问题)等 MRO MRO即method resolution order,用于判断子类调用的属性来自于哪个父类.在 ...

  9. C++中的多重继承与虚继承的问题

    1.C++支持多重继承,但是一般情况下,建议使用单一继承. 类D继承自B类和C类,而B类和C类都继承自类A,因此出现下图所示情况: A          A \          / B     C ...

随机推荐

  1. StrategyPattern(策略模式)-----Java/.Net

    在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改.这种类型的设计模式属于行为型模式. 在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 ...

  2. sql函数实用——字符函数(sqlserver与mysql对比)

    1.获取长度 sqlserver写法:关键字:len()    获取参数的字符数量 select  Len('aksjdhh')    输出结果 7 select len('张无忌ooo')   输出 ...

  3. Codeforces Round #604 (Div. 2) E. Beautiful Mirrors 题解 组合数学

    题目链接:https://codeforces.com/contest/1265/problem/E 题目大意: 有 \(n\) 个步骤,第 \(i\) 个步骤成功的概率是 \(P_i\) ,每一步只 ...

  4. 学了java,我才发现台球还可以这样玩!

    桌球小游戏的尝试 桌球是人们日常生活中都能接触到的一种娱乐活动,随着互联网技术的发展,手机上也有了很多桌球小游戏,让人们随时随地都能打两把.   今天分享一个用java编写的桌球小游戏 代码如下:  ...

  5. Theia APIs——Preferences

    上一篇:Theia APIs——命令和快捷键 Preferences Theia有一个preference service,模块可以通过它来获取preference的值,提供默认的preference ...

  6. Redis 持久化的两种方案

    reids是一个key-value存储系统,为了保证效率,缓存在内存中,但是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,以保证数据的持久化. 所以:redis是一个支持持 ...

  7. C++ | C++ 基础知识 | 指针、数组与引用

    1.指针 在 C++ 语言中存放及使用内存地址是通过指针和引用完成的. char c = 'a'; // 声明 c 变量,c 变量存储的是 'a' 的值. char* p = &c; // 声 ...

  8. .Net Core - AgileHttp

    2020年新年将至,先预祝.Net Core越来越好. 做了这么多年一线开发,经常跟Http打交道.比如调用三方的Webservice,比如集成微信支付的时候服务端发起Prepay支付.特别是现在分布 ...

  9. ArcGIS for JavaScript 开发智能提示

    开发如果没有智能提示,可想而知是一件多举痛苦的事情,好在Esri为Visual Studio 2010.Aptana3提供了一个插件,这样就使我们在使用ArcGIS API for Javascrip ...

  10. Spring Boot 入门(十):集成Redis哨兵模式,实现Mybatis二级缓存

    本片文章续<Spring Boot 入门(九):集成Quartz定时任务>.本文主要基于redis实现了mybatis二级缓存.较redis缓存,mybaits自带缓存存在缺点(自行谷歌) ...