当前位置: 首页 > 编程笔记 >

Python多重继承之菱形继承的实例详解

陈项禹
2023-03-14
本文向大家介绍Python多重继承之菱形继承的实例详解,包括了Python多重继承之菱形继承的实例详解的使用技巧和注意事项,需要的朋友参考一下

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

语法

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

菱形继承

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

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

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

  • 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多重继承之菱形继承的实例详解,希望对大家有所帮助!

 类似资料:
  • 主要内容:多继承下的构造函数,命名冲突在前面的例子中,派生类都只有一个基类,称为 单继承(Single Inheritance)。除此之外, C++也支持 多继承(Multiple Inheritance),即一个派生类可以有两个或多个基类。 多继承容易让代码逻辑复杂、思路混乱,一直备受争议,中小型项目中较少使用,后来的 Java、 C#、 PHP 等干脆取消了多继承。 多继承的语法也很简单,将多个基类用逗号隔开即可。例如已声明了类A

  • 本文向大家介绍python中的多重继承实例讲解,包括了python中的多重继承实例讲解的使用技巧和注意事项,需要的朋友参考一下 python和C++一样,支持多继承。概念虽然容易,但是困难的工作是如果子类调用一个自身没有定义的属性,它是按照何种顺序去到父类寻找呢,尤其是众多父类中有多个都包含该同名属性。 对经典类和新式类来说,属性的查找顺序是不同的。现在我们分别看一下经典类和新式类两种不同的表现:

  • 在面向对象的程序设计中,定义一个新的 class 的时候,可以从某个现有的 class 继承,新的 class 称为子类,而被继承的 class 称为基类、父类或超类。 Python 中继承的语法如下: class Parent: pass class Child(Parent): pass 在第 1 行,定义了父类 Parent; 在第 4 行,定义了子类 Child,语法

  • 继承是面向对象编程的一个重要的方式,因为通过继承,子类就可以扩展父类的功能。 回忆一下Animal类层次的设计,假设我们要实现以下4种动物: Dog - 狗狗; Bat - 蝙蝠; Parrot - 鹦鹉; Ostrich - 鸵鸟。 如果按照哺乳动物和鸟类归类,我们可以设计出这样的类的层次: 但是如果按照“能跑”和“能飞”来归类,我们就应该设计出这样的类的层次: 如果要把上面的两种分类都包含进来

  • 继承是面向对象编程的一个重要的方式,因为通过继承,子类就可以扩展父类的功能。 回忆一下Animal类层次的设计,假设我们要实现以下4种动物: Dog - 狗狗; Bat - 蝙蝠; Parrot - 鹦鹉; Ostrich - 鸵鸟。 如果按照哺乳动物和鸟类归类,我们可以设计出这样的类的层次: ┌───────────────┐ │

  • 本文向大家介绍关于C++中菱形继承和虚继承的问题总结,包括了关于C++中菱形继承和虚继承的问题总结的使用技巧和注意事项,需要的朋友参考一下 前言 菱形继承是多重继承中跑不掉的,Java拿掉了多重继承,辅之以接口。C++中虽然没有明确说明接口这种东西,但是只有纯虚函数的类可以看作Java中的接口。在多重继承中建议使用“接口”,来避免多重继承中可能出现的各种问题。本文将给大家详细介绍关于C++菱形继承

  • 本文向大家介绍js对象继承之原型链继承实例,包括了js对象继承之原型链继承实例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了js对象继承之原型链继承的用法。分享给大家供大家参考。具体分析如下: 其它说明:kitty也是有构造方法的,即new Object()。Object默认也有一些方法和属性,见javascript手册中的 "object对象"。同时,它也有原型,只是为空而已 { }。

  • 本文向大家介绍JavaScript中的继承之类继承,包括了JavaScript中的继承之类继承的使用技巧和注意事项,需要的朋友参考一下 继承简介       在JS中继承是一个非常复杂的话题,比其他任何面向对象语言中的继承都复杂得多。在大多数其他面向对象语言中,继承一个类只需使用一个关键字即可。在JS中想要达到继承公用成员的目的,需要采取一系列措施。JS属于原型式继承,得益于这种灵活性,我们既可以