当前位置: 首页 > news >正文

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 中&#xff0c;MRO&#xff08;Method Resolution Order&#xff0c;方法解析顺序&#xff09;是指类继承体系中&#xff0c;Python 如何确定在调用方法时的解析顺序。MRO 决定了在多继承环境下&#xff0c;Python 如何寻找方法或属性&#xff0c;即它会根据一定规则…...

MySQL表的内外连接

内连接 其实就是from 两个表 把笛卡尔积的表 再用where 进行条件筛选 ——之前我们写的多表查询就是内连接 基本格式&#xff1a; 外链接 没有向内连接那样真的把两个表连接形式一个表显示&#xff0c;而只是建立关系 外连接分为左链接和右链接 左链接 联合查询时候&#…...

系统架构设计师:软件架构的演化和维护

简简单单 Online zuozuo: 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo :本心、输入输出、结果 简简单单 Online zuozuo : 文章目录 系统架构设计师:软件架构的演化和维护前言软件架构演化的重要性面向对象的软件架构演…...

QT的dropEvent函数进入不了

在使用QT想实现拖拽功能的时候&#xff0c;发现了dropEvent没有调用运行&#xff0c;遂查找原因&#xff1a; 首先是网上都说要在dragEnterEvent里面使用event->accept(); 但我这边在出现问题之前就已经这样做了&#xff1a; void CanvasView::dragEnterEvent(QDragEnterEv…...

Spring Boot 入门

前言 Spring Boot 是一个开源的 Java 基础框架&#xff0c;用于创建独立、生产级的基于 Spring 的应用程序。它简化了基于 Spring 的应用开发&#xff0c;通过提供一系列的“起步依赖”来快速启动和运行 Spring 应用。本文将带你深入了解 Spring Boot 的核心概念、关键特性&am…...

LDD学习2--Scull(TODO)

《Linux Device Drivers》&#xff08;LDD&#xff09;书籍中的 scull&#xff08;Simple Character Utility for Loading Localities&#xff09;是一个用于演示 Linux 字符设备驱动程序编写的示例代码。它为理解 Linux 内核模块和字符设备驱动程序的编写提供了基础实践平台&a…...

【算法-堆排序】

堆排序是一种基于堆这种数据结构的比较排序算法&#xff0c;它是一种原地、不稳定的排序算法&#xff0c;时间复杂度为 O(n log n)。堆排序的基本思想是将数组构建成一个二叉堆&#xff0c;并通过反复调整堆顶和未排序部分之间的关系来实现排序。 堆的定义 堆是一种特殊的完全…...

音视频入门基础:AAC专题(4)——ADTS格式的AAC裸流实例分析

音视频入门基础&#xff1a;AAC专题系列文章&#xff1a; 音视频入门基础&#xff1a;AAC专题&#xff08;1&#xff09;——AAC官方文档下载 音视频入门基础&#xff1a;AAC专题&#xff08;2&#xff09;——使用FFmpeg命令生成AAC裸流文件 音视频入门基础&#xff1a;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的选用

写在前言&#xff1a; 刚写了Windows PC的不同editions的选用&#xff0c;趁热&#xff0c;把Linux不同的Distribution选用也介绍下&#xff0c;希望童鞋们可以了解-->理解-->深入了解-->深入理解--...以致于能掌握特定版本的Linux的使用甚者精通。……^.^…… so&a…...

cesium效果不酷炫怎么办--增加渲染器

DrawCommand 可以发挥 WebGL 全部潜力吗&#xff1f; 回答&#xff1a; Cesium 的 DrawCommand 是一个用于表示 WebGL 渲染管线中单个绘制调用的低级抽象。它封装了执行 WebGL 绘制所需的所有信息&#xff0c;包括着色器程序、顶点数组、渲染状态、统一变量&#xff08;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论文阅读

文章链接&#xff1a;https://arxiv.org/abs/2308.01979http://arxiv.org/abs/2212.10505https://arxiv.org/abs/2308.01979 源码链接&#xff1a;https://github.com/cse-ai-lab/RealCQA 启发&#xff1a;two-stage方法可能是未来主要研究方向&#xff0c;能够增强模型可解释…...

从 HDFS 迁移到 MinIO 企业对象存储

云原生、面向 Kubernetes 、基于微服务的架构推动了对 MinIO 等网络存储的需求。在云原生环境中&#xff0c;对象存储的优势很多 - 它允许独立于存储硬件对计算硬件进行弹性扩展。它使应用程序无状态&#xff0c;因为状态是通过网络存储的&#xff0c;并且通过降低操作复杂性&a…...

Rust 常见问题汇总

问题1&#xff1a; cargo build 一直提示Blocking waiting for file lock on package cache。 在 cargo.toml 文件中添加了依赖之后&#xff0c;运行 cargo build 命令时&#xff0c;如果卡在 blocking waiting for file lock on package cache lock 这里&#xff0c; 后来发…...

java泛型类与泛型方法

Java泛型类和泛型方法是Java泛型编程中的重要组成部分。它们允许开发者编写类型安全且高度复用的代码。下面详细介绍泛型类和泛型方法的概念、用法和示例。 泛型类 泛型类是在类定义中使用类型参数的类&#xff0c;可以指定具体的类型实例化该类。这样可以确保类型安全&#…...

Android String资源文件中,空格、换行以及特殊字符如何表示

空格&#xff1a; 例&#xff1a;<string name"test">test test</string> 换行&#xff1a;\n 例&#xff1a;<string name"test">test \n test</string> tab&#xff1a;\t …...

CUDA及GPU学习资源汇总

CUDA C Programming Guide 的中文翻译版GPU中的SM和warp的关系推荐几个不错的CUDA入门教程CUDA编程入门极简教程...

uniapp vue3 梯形选项卡组件

实现的效果图&#xff1a; 切换选项卡显示不同的内容&#xff0c;把这个选项卡做成了一个组件&#xff0c;需要的自取。 // 组件名为 trapezoidalTab <template> <view class"pd24"><view class"nav"><!-- 左侧 --><view cla…...

如何在微信小程序中实现WebSocket连接

微信小程序作为一种全新的应用形态&#xff0c;凭借其便捷性、易用性受到了广大用户的喜爱。在实际开发过程中&#xff0c;实时通信功能是很多小程序必备的需求。WebSocket作为一种在单个TCP连接上进行全双工通信的协议&#xff0c;能够实现客户端与服务器之间的实时通信。本文…...

OpenLayers 可视化之热力图

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 热力图&#xff08;Heatmap&#xff09;又叫热点图&#xff0c;是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 &#xff1a;HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09; 默认端口 &#xff1a;HTTP 使用 80 端口&#xff0c;HTTPS 使用 443 端口。 请求方法 &#xff1a; GET &#xff1a;用于获取资源&#xff0c;…...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码&#xff0c;因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存&#xff0c;无论是github还是gittee&#xff0c;都是一种基于git去保存代码的形式&#xff0c;这样保存代码…...

C#学习第29天:表达式树(Expression Trees)

目录 什么是表达式树&#xff1f; 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持&#xff1a; 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...