python菱形问题

news/2025/3/14 5:47:43/

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

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

1、普通继承

子类中调用父类方法并不难,下面是一个简单示例

class A:def __init__(self):self.attr_a = 1print('执行A的初始化函数')class B(A):def __init__(self):A.__init__(self)self.attr_b = 2b = B()
print(b.attr_a, b.attr_b)

输出结果:

执行A的初始化函数
1 2

 2. 菱形继承

在子类中直接调用父类的方法虽然可行,但在特定场景下会有问题,比如菱形继承

class A:def __init__(self):self.attr_a = 1print('执行A的初始化函数')class B(A):def __init__(self):A.__init__(self)self.attr_b = 2print('执行B的初始化函数')class C(A):def __init__(self):A.__init__(self)self.attr_c = 3print('执行C的初始化函数')class D(B, C):def __init__(self):B.__init__(self)C.__init__(self)self.attr_d = 4print('执行D的初始化函数')d = D()
print(d.attr_a, d.attr_b, d.attr_c, d.attr_d)

A是B和C的父类,D同时继承了B和C, 这样就形成了菱形继承,所谓菱形继承,仅仅是因形状上像菱形。程序执行结果

执行A的初始化函数
执行B的初始化函数
执行A的初始化函数
执行C的初始化函数
执行D的初始化函数
1 2 3 4

应该注意到,类A的初始化函数被执行了两次,这是一个非常危险的行为,如果A的初始化函数执行了一些一个进程中只能执行一次的代码,这样的多进程就会导致严重的问题, super的引入就是为了解决这种问题。

class A:def __init__(self):self.attr_a = 1print('执行A的初始化函数')class B(A):def __init__(self):super().__init__()self.attr_b = 2print('执行B的初始化函数')class C(A):def __init__(self):super().__init__()self.attr_c = 3print('执行C的初始化函数')class D(B, C):def __init__(self):super().__init__()self.attr_d = 4print('执行D的初始化函数')d = D()
print(d.attr_a, d.attr_b, d.attr_c, d.attr_d)

执行结果

执行A的初始化函数
执行C的初始化函数
执行B的初始化函数
执行D的初始化函数
1 2 3 4

在D的初始化函数中,只使用了一行代码super().__init__(), 就将两个父类B和C的初始化函数都执行了, 而且不会重复执行A的初始化函数,这些都是super帮助我们完成的。 

3. MRO

在第2小结的示例中, 执行D的初始化函数,使用了super,会自动执行B,C的初始化函数,那么B与C的初始化函数先执行哪个呢?对于这个问题,在我们定义类时,python会计算出一个方法解析顺序列表,也就是MRO,这个MRO列表就是一个简单的所有基类的线性顺序表, 类的mro()方法可以获得MRO

print(D.mro())

输出结果

[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

按照顺序,先执行B的初始化函数,在执行C的初始化函数,最后执行A的初始化函数。

4. 带参数的super方法使用示例

为了简化代码,前面的示例代码在执行super方法时,都没有使用任何参数,下面提供了有参数的示例

class A:def __init__(self):self.attr_a = 1def add(self, a, b):return a + bclass B(A):def __init__(self):super().__init__()self.attr_b = 2def add(self, a, b):print('执行B的add')return a + b + 1class C(A):def __init__(self):super().__init__()self.attr_c = 3def add(self, a, b):print('执行C的add')return a + b + 2class D(B, C):def __init__(self):super().__init__()self.attr_d = 4def add(self, a, b):return super().add(a, b)d = D()
print(d.add(1, 2))

程序执行结果

执行B的add
4

D的父类B和C都有add方法,在D的add方法时,super().add()会根据mro来决定调用哪个父类的add方法,根据顺序,应该执行B的add方法, 如果你希望执行C的add方法, 那么可以这样来实现add方法

def add(self, a, b):return super(B, self).add(a, b)

在mro列表里,B的后面是C, super的第一个函数指定为B, 第二个参数设置为self,就会执行C的add方法。

引文:python面向对象--super() | 酷python


http://www.ppmy.cn/news/1036677.html

相关文章

蓝桥杯嵌入式省一教程:(二)LCD显示

在嵌入式开发中&#xff0c;屏幕显示是一个非常重要的功能。同时&#xff0c;其移植对于初学者来说较为复杂&#xff0c;需要较好地掌握I2C或SPI等通讯协议。然而&#xff0c;在蓝桥杯中&#xff0c;比赛方已经为我们提供了与LCD有关的库&#xff0c;这让我们能够简单方便地使用…

计算机视觉目标检测性能指标

目录 精确率&#xff08;Precision&#xff09;和召回率&#xff08;Recall&#xff09; F1分数&#xff08;F1 Score&#xff09; IoU&#xff08;Intersection over Union&#xff09; P-R曲线&#xff08;Precision-Recall Curve&#xff09;和 AP mAP&#xff08;mean…

谈谈网络协议的定义、组成和重要性

个人主页&#xff1a;insist--个人主页​​​​​​ 本文专栏&#xff1a;网络基础——带你走进网络世界 本专栏会持续更新网络基础知识&#xff0c;希望大家多多支持&#xff0c;让我们一起探索这个神奇而广阔的网络世界。 目录 一、网络协议的定义 二、网络协议的组成 1、…

Programming abstractions in C阅读笔记: p114-p117

《Programming Abstractions in C》学习第48天&#xff0c;p114-p117&#xff0c;​总结如下&#xff1a; 一、技术总结 主要通过random number介绍了随机数的相关用法&#xff0c;interface​示例(random.h)​&#xff0c;client program示例(craps.c)。 #include <stdio…

非计算机科班如何顺利转码进入计算机领域?

文章目录 如何规划才能实现转码&#xff1f;计算机岗位发展前景&#xff1f;现阶段转码 总结 &#x1f389;欢迎来到Java学习路线专栏~探索非计算机科班如何顺利转码进入计算机领域 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#xff1a;IT陈寒的博客&#x1f3…

大数据:Numpy基础应用详解

Numpy基础应用 Numpy 是一个开源的 Python 科学计算库&#xff0c;用于快速处理任意维度的数组。Numpy 支持常见的数组和矩阵操作&#xff0c;对于同样的数值计算任务&#xff0c;使用 NumPy 不仅代码要简洁的多&#xff0c;而且 NumPy 的性能远远优于原生 Python&#xff0c;…

中科亿海微FIFO使用

引言 FPGA&#xff08;现场可编程门阵列&#xff09;是一种可编程逻辑器件&#xff0c;具有灵活性和可重构性&#xff0c;广泛用于数字电路设计和嵌入式系统开发。在FPGA中&#xff0c;FIFO&#xff08;First-In, First-Out&#xff09;是一种常见的存储器结构&#xff0c;用于…

python根据已有列计算其他列

根据已有列计算其他列 1、根据已有列新增列2、根据已有列修改其他列 读取数据源 import pandas as pd # 读取数据 path1 r../excelFile-j/flower.csv df_data pd.read_csv(path1) # df_data 内容1、根据已有列新增列 方式一&#xff1a;根据单列 df_data["LengthAdd&q…