Python 中的方法解析顺序(MRO)
在 Python 中,MRO(Method Resolution Order,方法解析顺序)是指类继承体系中,Python 如何确定在调用方法时的解析顺序。MRO 决定了在多继承环境下,Python 如何寻找方法或属性,即它会根据一定规则从父类中查找方法或属性,避免重复继承带来的歧义。
1. MRO 介绍
在 Python 中,类可通过多继承(即从多个父类继承)来获得不同父类的功能。为了避免由于多继承带来的冲突和不确定性,Python 使用了 MRO 来确定方法调用的顺序。
从 Python 2.3 [1]开始,Python 使用 C3 线性化算法 来决定类的 MRO。Python 的继承系统遵循该算法,这使得继承路径清晰且无二义性。
2. MRO 计算步骤
(1)MRO 计算步骤
- 从当前类开始,将当前类添加到 MRO 列表的末尾。
- 遍历当前类的基类列表。
- 对于每个基类,如果它还没有被添加到 MRO 列表中,将其添加到 MRO 列表的末尾,并递归地重复步骤 2。
- 如果基类列表为空,则结束。
(2)查看类的 MRO
在 Python 中,可通过 __mro__
属性或内置的 mro()
方法来查看类的 MRO。如下所示:
class A:def foo(self):print("A")class B(A):def foo(self):print("B")class C(A):def foo(self):print("C")class D(B, C):pass# 查看类 D 的 MRO
print(D.__mro__)
# 或者
print(D.mro())
输出结果显示 D 类的 MRO 顺序:
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
这个 MRO 表示 Python 将首先在 D 类中查找方法,如果没有找到,再去 B 类,然后是 C 类,接着是 A 类,最后是 object
类。
3. C3 线性化算法
(1)算法特性
- 单调性:MRO 列表在继承过程中是单调的,这意味着一旦一个类被添加到 MRO 中,它就不会再被添加到后面的类中。
- 非循环性:MRO 列表不会包含任何循环。
- 保持子类顺序:如果一个类 B 继承自类 A 和类 C,那么 A 应该在 C 之前出现在 MRO 中。
(2)简单示例
假设有以下类继承关系,如下所示:
class A:passclass B(A):passclass C(A):passclass D(B, C):pass
MRO 计算过程,如下所示:
- D 类的直接父类是 B 和 C,因此 MRO 将从这两个类开始。为了保证类 B 在类 C 之前解析(因为 B 在 D 类的声明中出现在前面),MRO 按顺序选择 B 和 C。
- 然后,MRO 会解析 B 和 C 各自的父类 A,确保 A 只出现一次,且在 B 和 C 之后。
- 最后,所有类都继承自
object
类。
这样最终 MRO 为 [D, B, C, A, object]
。
4. super()
函数与 MRO
在多继承中,super()
函数使用 MRO 来决定调用顺序。super()
会沿着 MRO 顺序依次调用下一个类的方法。如下所示:
class A:def foo(self):print("A")class B(A):def foo(self):super().foo()print("B")class C(A):def foo(self):super().foo()print("C")class D(B, C):def foo(self):super().foo()print("D")d = D()
d.foo()
这里 super()
将沿着 D 类的 MRO 顺序调用 foo()
方法。输出结果为:
A
C
B
D
这表明 Python 沿着 MRO 的顺序依次调用了 A -> C -> B -> D。简单理解,foo()
方法执行顺序与 D 类的 MRO 顺序相反。
5. MRO 解决的问题
(1)避免菱形继承问题
在多重继承中,如果不同的父类继承自同一个祖先类,MRO 确保这个祖先类的方法只会调用一次。
(2)保证方法查找的有序性
MRO 保证了在多继承中有明确的解析顺序,不会出现不确定性或冲突。
MRO 是 Python 中一个复杂但重要的概念,它通过 C3 线性化算法计算出一个类的所有基类的有序列表,这个列表决定了方法或属性在多重继承中的查找顺序。理解 MRO 有助于编写更清晰、更健壮的 Python 代码。
参考文献
[1] The Python 2.3 Method Resolution Order:https://www.python.org/download/releases/2.3/mro/
[2] Make MRO topological sorted:https://discuss.python.org/t/make-mro-topological-sorted/32300
NLP工程化(星球号)
相关文章:

Python 中的方法解析顺序(MRO)
在 Python 中,MRO(Method Resolution Order,方法解析顺序)是指类继承体系中,Python 如何确定在调用方法时的解析顺序。MRO 决定了在多继承环境下,Python 如何寻找方法或属性,即它会根据一定规则…...

MySQL表的内外连接
内连接 其实就是from 两个表 把笛卡尔积的表 再用where 进行条件筛选 ——之前我们写的多表查询就是内连接 基本格式: 外链接 没有向内连接那样真的把两个表连接形式一个表显示,而只是建立关系 外连接分为左链接和右链接 左链接 联合查询时候&#…...
系统架构设计师:软件架构的演化和维护
简简单单 Online zuozuo: 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo :本心、输入输出、结果 简简单单 Online zuozuo : 文章目录 系统架构设计师:软件架构的演化和维护前言软件架构演化的重要性面向对象的软件架构演…...
QT的dropEvent函数进入不了
在使用QT想实现拖拽功能的时候,发现了dropEvent没有调用运行,遂查找原因: 首先是网上都说要在dragEnterEvent里面使用event->accept(); 但我这边在出现问题之前就已经这样做了: void CanvasView::dragEnterEvent(QDragEnterEv…...

Spring Boot 入门
前言 Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级的基于 Spring 的应用程序。它简化了基于 Spring 的应用开发,通过提供一系列的“起步依赖”来快速启动和运行 Spring 应用。本文将带你深入了解 Spring Boot 的核心概念、关键特性&am…...
LDD学习2--Scull(TODO)
《Linux Device Drivers》(LDD)书籍中的 scull(Simple Character Utility for Loading Localities)是一个用于演示 Linux 字符设备驱动程序编写的示例代码。它为理解 Linux 内核模块和字符设备驱动程序的编写提供了基础实践平台&a…...
【算法-堆排序】
堆排序是一种基于堆这种数据结构的比较排序算法,它是一种原地、不稳定的排序算法,时间复杂度为 O(n log n)。堆排序的基本思想是将数组构建成一个二叉堆,并通过反复调整堆顶和未排序部分之间的关系来实现排序。 堆的定义 堆是一种特殊的完全…...

音视频入门基础:AAC专题(4)——ADTS格式的AAC裸流实例分析
音视频入门基础:AAC专题系列文章: 音视频入门基础:AAC专题(1)——AAC官方文档下载 音视频入门基础:AAC专题(2)——使用FFmpeg命令生成AAC裸流文件 音视频入门基础:AAC…...

【第33章】Spring Cloud之SkyWalking服务链路追踪
文章目录 前言一、介绍1. 架构图2. SkyWalking APM 二、服务端和控制台1. 下载2. 解压3. 初始化数据库4. 增加驱动5. 修改后端配置6. 启动7. 访问控制台8. 数据库表 三、客户端1. 下载2. 设置java代理3. idea配置3.1 环境变量3.2 JVM参数3.3 启动日志 4. 启用网关插件 四、链路…...

如何选择OS--Linux不同Distribution的选用
写在前言: 刚写了Windows PC的不同editions的选用,趁热,把Linux不同的Distribution选用也介绍下,希望童鞋们可以了解-->理解-->深入了解-->深入理解--...以致于能掌握特定版本的Linux的使用甚者精通。……^.^…… so&a…...
cesium效果不酷炫怎么办--增加渲染器
DrawCommand 可以发挥 WebGL 全部潜力吗? 回答: Cesium 的 DrawCommand 是一个用于表示 WebGL 渲染管线中单个绘制调用的低级抽象。它封装了执行 WebGL 绘制所需的所有信息,包括着色器程序、顶点数组、渲染状态、统一变量(unifo…...

计算机网络:概述 --- 体系结构
目录 一. 体系结构总览 1.1 OSI七层协议体系结构 1.2 TCP/IP四层(或五层)模型结构 二. 数据传输过程 2.1 同网段传输 2.2 跨网段传输 三. 体系结构相关概念 3.1 实体 3.2 协议 3.3 服务 这里我们专门来讲一下计算机网络中的体系结构。其实我们之前…...

DEPLOT: One-shot visual language reasoning by plot-to-table translation论文阅读
文章链接:https://arxiv.org/abs/2308.01979http://arxiv.org/abs/2212.10505https://arxiv.org/abs/2308.01979 源码链接:https://github.com/cse-ai-lab/RealCQA 启发:two-stage方法可能是未来主要研究方向,能够增强模型可解释…...

从 HDFS 迁移到 MinIO 企业对象存储
云原生、面向 Kubernetes 、基于微服务的架构推动了对 MinIO 等网络存储的需求。在云原生环境中,对象存储的优势很多 - 它允许独立于存储硬件对计算硬件进行弹性扩展。它使应用程序无状态,因为状态是通过网络存储的,并且通过降低操作复杂性&a…...
Rust 常见问题汇总
问题1: cargo build 一直提示Blocking waiting for file lock on package cache。 在 cargo.toml 文件中添加了依赖之后,运行 cargo build 命令时,如果卡在 blocking waiting for file lock on package cache lock 这里, 后来发…...
java泛型类与泛型方法
Java泛型类和泛型方法是Java泛型编程中的重要组成部分。它们允许开发者编写类型安全且高度复用的代码。下面详细介绍泛型类和泛型方法的概念、用法和示例。 泛型类 泛型类是在类定义中使用类型参数的类,可以指定具体的类型实例化该类。这样可以确保类型安全&#…...
Android String资源文件中,空格、换行以及特殊字符如何表示
空格: 例:<string name"test">test test</string> 换行:\n 例:<string name"test">test \n test</string> tab:\t …...
CUDA及GPU学习资源汇总
CUDA C Programming Guide 的中文翻译版GPU中的SM和warp的关系推荐几个不错的CUDA入门教程CUDA编程入门极简教程...

uniapp vue3 梯形选项卡组件
实现的效果图: 切换选项卡显示不同的内容,把这个选项卡做成了一个组件,需要的自取。 // 组件名为 trapezoidalTab <template> <view class"pd24"><view class"nav"><!-- 左侧 --><view cla…...
如何在微信小程序中实现WebSocket连接
微信小程序作为一种全新的应用形态,凭借其便捷性、易用性受到了广大用户的喜爱。在实际开发过程中,实时通信功能是很多小程序必备的需求。WebSocket作为一种在单个TCP连接上进行全双工通信的协议,能够实现客户端与服务器之间的实时通信。本文…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error
在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...
前端中slice和splic的区别
1. slice slice 用于从数组中提取一部分元素,返回一个新的数组。 特点: 不修改原数组:slice 不会改变原数组,而是返回一个新的数组。提取数组的部分:slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...