Python 中 `finally` 的执行时机与 `return` 的微妙关系

文章目录

    • Python 中 `finally` 的执行时机与 `return` 的微妙关系
      • 一、`finally` 的执行时机
        • 示例
      • 二、`return` 与 `finally` 的交互:可变对象的陷阱
        • 示例 :可变对象在 `finally` 中被修改
        • 示例 :不可变对象的安全隔离
      • 三、`finally` 中的 `return`:危险的覆盖行为
        • 示例 4:`finally` 覆盖返回值
        • 示例 5:`finally` 吞没异常
      • 四、总结与最佳实践

Python 中 finally 的执行时机与 return 的微妙关系

一、finally 的执行时机

在 Python 中,finally 代码块的执行遵循一个核心原则:无论 tryexcept 中是否发生异常、是否遇到 returnbreakfinally 总会执行。这一机制使得 finally 成为资源清理(如关闭文件、释放锁)的黄金位置。

示例
def basic_finally():try:print("执行 try 块")return "try 返回值"except:passfinally:print("执行 finally 块")print(basic_finally())

输出:

执行 try 块
执行 finally 块
try 返回值

关键结论

  • finallyreturn 之后声明,但在 return 之前执行
  • 函数返回值在 finally 执行前被暂存,但 finally 中的操作仍可能影响返回值(见下文)。

二、returnfinally 的交互:可变对象的陷阱

return 遇到可变对象(如列表、字典)时,finally 中的代码可能“悄无声息”地修改返回值。这是因为 Python 返回的是对象的引用,而非副本。

示例 :可变对象在 finally 中被修改
def mutable_return():x = [1, 2, 3]try:x.append(4)return x  # 暂存返回值 [1,2,3,4]finally:x.append(5)  # 修改原列表print("finally 中修改后的 x:", x)result = mutable_return()
print("最终返回值:", result)

输出:

finally 中修改后的 x: [1, 2, 3, 4, 5]
最终返回值: [1, 2, 3, 4, 5]

函数中的return语句会将当前的值暂存,然后执行finally块,如果在finally中修改了返回值引用的对象,对于可变对象来说,这些修改会反映到返回值中,因为返回的是对象的引用,而不是副本

关键结论

  • return x 暂存的是列表 x 的引用,而非数据副本。
  • finally 中对 x 的修改会直接影响返回值,因为它们指向同一内存地址。

示例 :不可变对象的安全隔离
def immutable_return():x = 100try:x += 10return x  # 暂存返回值 110finally:x += 20  # 创建新对象,不影响原返回值print("finally 中的 x:", x)result = immutable_return()
print("最终返回值:", result)

输出:

finally 中的 x: 130
最终返回值: 110

关键结论

  • 不可变对象(如整数、字符串)的修改会创建新对象,原始返回值不受影响。
  • finally 中的操作仅影响函数内的局部变量,与已暂存的返回值无关。

三、finally 中的 return:危险的覆盖行为

finally 中也有 return,它会直接覆盖之前的返回值,并可能导致异常被静默忽略。

示例 4:finally 覆盖返回值
def dangerous_finally():try:return "来自 try 的返回值"finally:return "来自 finally 的返回值"  # 覆盖 try 的返回值print(dangerous_finally())

输出:

来自 finally 的返回值
示例 5:finally 吞没异常
def hide_exception():try:raise ValueError("严重错误!")except:return "来自 except 的返回值"finally:return "来自 finally 的返回值"  # 覆盖异常处理结果print(hide_exception())

输出:

来自 finally 的返回值

关键结论

  • 避免在 finally 中使用 return:除非明确需要覆盖返回值或忽略异常。
  • 覆盖行为会隐藏潜在错误,导致调试困难。

四、总结与最佳实践

  1. 执行顺序
    try/except → 暂存返回值 → 执行 finally → 返回暂存值

  2. 返回值规则

    • 对可变对象:finally 中的修改直接影响返回值(返回的是引用)。
    • 对不可变对象:finally 中的修改不影响返回值(返回的是副本)。
  3. 避坑指南

    • 禁止finally 中使用 return,除非有明确需求。
    • 若需返回可变对象,优先返回其副本(如 return x.copy())。
    • finally 中仅处理资源释放,避免业务逻辑。

若有错误与不足请指出,关注DPT一起进步吧!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/69955.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

问题的价值 ( Value of Question ) 公式

一、什么是问题的价值 我们的人生、工作的期间、瞬息万变的商业环境中,我们必然会面对很多问题,也会提出很多问题。 但这些问题是否具有回答的 价值,应该如何 衡量 呢? 简单如,女朋友问今晚应该吃什么、世界如何才能…

一文了解阿里的 Qwen2.5 模型

最近被DeepSeek刷屏了,但是在之外阿里在2025年1月28日推出了Qwen 2.5 Max模型。 Qwen2.5-Max 的特点:大规模的 MoE 模型,预训练于超 20 万亿 tokens,并经过 SFT 和 RLHF 后训练。 性能表现:在多个基准测试中与领先模型…

基于Django的Boss直聘IT岗位可视化分析系统的设计与实现

【Django】基于Django的Boss直聘IT岗位可视化分析系统的设计与实现(完整系统源码开发笔记详细部署教程)✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 该系统采用Python作为主要开发语言,利用Django这一高效、安全的W…

Hive:复杂数据类型之Map函数

Map函数 是Hive里面的一种复杂数据类型, 用于存储键值对集合。Map中的键和值可以是基础类型或复合类型,这使得Map在处理需要关联存储信息的数据时非常有用。 定义map时,需声明2个属性: key 和 value , map中是 key value 组成一个元素 key-value, key必须为原始类…

计算机毕业设计Python动漫推荐系统 漫画推荐系统 动漫视频推荐系统 机器学习 bilibili动漫爬虫 数据可视化 数据分析 大数据毕业设计

温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…

2025年02月02日Github流行趋势

项目名称:oumi 项目地址url:https://github.com/oumi-ai/oumi 项目语言:Python 历史star数:1416 今日star数:205 项目维护者:xrdaukar, oelachqar, taenin, wizeng23, kaisopos 项目简介:构建最…

谭浩强C语言程序设计(3) 7章

1、递归实现N的阶乘 c复制 #include <cstdio> // 包含标准输入输出库// 计算n的阶乘 int total 0; // 定义全局变量total用于存储阶乘结果// 递归函数计算阶乘 int fac(int a){// 如果输入的数小于0&#xff0c;输出错误信息if (a < 0){printf("%d < 0,err…

python算法和数据结构刷题[2]:链表、队列、栈

链表 链表的节点定义&#xff1a; class Node():def __init__(self,item,nextNone):self.itemitemself.nextNone 删除节点&#xff1a; 删除节点前的节点的next指针指向删除节点的后一个节点 添加节点&#xff1a; 单链表 class Node():"""单链表的结点&quo…

网络工程师 (13)时间管理

一、定义与重要性 项目时间管理是指为确保项目按时完成而采取的一系列规划、安排和控制活动。它始于项目启动阶段&#xff0c;贯穿整个项目生命周期&#xff0c;直至项目结束。时间管理对于项目的成功至关重要&#xff0c;它有助于项目团队明确工作目标和时间节点&#xff0c;增…

2025.2.1——四、php_rce RCE漏洞|PHP框架

题目来源&#xff1a;攻防世界 php_rce 目录 一、打开靶机&#xff0c;整理信息 二、解题思路 step 1&#xff1a;PHP框架漏洞以及RCE漏洞信息 1.PHP常用框架 2.RCE远程命令执行 step 2&#xff1a;根据靶机提示&#xff0c;寻找版本漏洞 step 3&#xff1a;进行攻击…

记录 | 基于MaxKB的文字生成视频

目录 前言一、安装SDK二、创建视频函数库三、调试更新时间 前言 参考文章&#xff1a;如何利用智谱全模态免费模型&#xff0c;生成大家都喜欢的图、文、视并茂的文章&#xff01; 自己的感想 本文记录了创建文字生成视频的函数库的过程。如果想复现本文&#xff0c;需要你逐一…

Error: Expected a mutable image

你的函数用了不支持的图片格式比如我的人脸检测&#xff0c;本来要RGB565我却用JPEG所以报错

深度学习查漏补缺:1.梯度消失、梯度爆炸和残差块

一、梯度消失 梯度消失的根本原因在于 激活函数的性质和链式法则的计算&#xff1a; 激活函数的导数很小&#xff1a; 常见的激活函数&#xff08;例如 Sigmoid 和 Tanh&#xff09;在输入较大或较小时&#xff0c;输出趋于饱和&#xff08;Sigmoid 的输出趋于 0 或 1&#xf…

c++可变参数详解

目录 引言 库的基本功能 va_start 宏: va_arg 宏 va_end 宏 va_copy 宏 使用 处理可变参数代码 C11可变参数模板 基本概念 sizeof... 运算符 包扩展 引言 在C编程中&#xff0c;处理不确定数量的参数是一个常见的需求。为了支持这种需求&#xff0c;C标准库提供了 &…

【自学嵌入式(8)天气时钟:天气模块开发、主函数编写】

天气时钟&#xff1a;天气模块开发、主函数编写 I2C协议和SPI协议I2C&#xff08;Inter-Integrated Circuit&#xff09;SPI&#xff08;Serial Peripheral Interface&#xff09; 天气模块心知天气预报使用HTTPClient类介绍主要功能常用函数注意事项 JSON介绍deserializeJson函…

SpringBoot的配置(配置文件、加载顺序、配置原理)

文章目录 SpringBoot的配置(配置文件、加载顺序、配置原理)一、引言二、配置文件1、配置文件的类型1.1、配置文件的使用 2、多环境配置 三、加载顺序四、配置原理五、使用示例1、配置文件2、配置类3、控制器 六、总结 SpringBoot的配置(配置文件、加载顺序、配置原理) 一、引言…

政务行业审计文件大数据高速报送解决方案

随着信息技术的快速发展&#xff0c;电子政务迎来了新的升级浪潮。国家相继出台了一系列信息化发展战略规划&#xff0c;如《国家信息化发展战略纲要》、《“十三五”国家信息化规划》等&#xff0c;这些政策为政务信息化工作指明了方向。 然而&#xff0c;在实际操作中&#x…

GMSL 明星产品之 MAX96724

上一篇文章中&#xff0c;我们介绍了摄像头侧 GMSL 加串器 MAX96717. 今天我们来介绍下 GMSL 解串器明星产品 MAX96724&#xff1a; 可将四路 GMSL™2/1 输入转换为 1 路、2 路或 4 路 MIPI D-PHY 或 C-PHY 输出。该器件支持通过符合 GMSL 通道规范的 50Ω 同轴电缆或 100Ω 屏…

机器学习--概览

一、机器学习基础概念 1. 定义 机器学习&#xff08;Machine Learning, ML&#xff09;&#xff1a;通过算法让计算机从数据中自动学习规律&#xff0c;并利用学习到的模型进行预测或决策&#xff0c;而无需显式编程。 2. 与编程的区别 传统编程机器学习输入&#xff1a;规…

MySQL5.5升级到MySQL5.7

【卸载原来的MySQL】 cmd打开命令提示符窗口&#xff08;管理员身份&#xff09;net stop mysql&#xff08;先停止MySQL服务&#xff09; 3.卸载 切换到原来5.5版本的bin目录&#xff0c;输入mysqld remove卸载服务 测试mysql -V查看Mysql版本还是5.5 查看了环境变量里的…