用抛出异常替代返回错误会拥有更稳定的返回值类型,它永远只会返回 Item 类型或是抛 出异常。

devtools/2025/2/18 16:07:57/

在处理异常时:

  1. 使用异常比返回错误码更稳定

    • create_item(name) 只会有两种情况:成功返回 Item抛出异常,不会返回错误码、None 或其他类型数据,这样可以减少调用者的判断逻辑。
  2. 异常会自动向上传播,提供了灵活性

    • 直接调用 create_item() 的地方可以选择不处理 CreateItemError,让异常继续上传,交给更高层的代码去处理,比如 UI 层或日志系统。
    • 这样避免了在每个调用处都写一堆 if/else 代码,提高了可读性。
  3. 但如果缺少统一异常处理,可能导致程序崩溃

    • 如果 CreateItemError 没有被任何地方捕获,它会一直向上传播,直到顶层,最终可能导致程序崩溃。
    • 解决方案是在主函数或入口点设置全局异常处理,例如:
      python">try:create_from_input()
      except CreateItemError as e:print(f"Unhandled CreateItemError: {e}")
      except Exception as e:print(f"Unexpected error: {e}")
      

为什么这样设计更合理?

1. 对比返回错误码

传统返回错误码的方式

python">def create_item(name):if len(name) > MAX_LENGTH_OF_NAME:return None, 'name too long'if len(get_current_items()) > MAX_ITEMS_QUOTA:return None, 'quota exceeded'return Item(name=name), ''item, err = create_item(name)
if err:print(f"Create item failed: {err}")
else:print(f"Item {name} created")
  • 问题
    • 需要判断 err,增加了调用方的额外工作。
    • 调用方可能忘记检查 err,导致程序异常行为。
    • 如果返回值结构变了(比如从 (Item, str) 变成 (Item, int)),调用方可能要改很多代码。
2. 使用异常的方式
python">def create_item(name):if len(name) > MAX_LENGTH_OF_NAME:raise CreateItemError('name too long')if len(get_current_items()) > MAX_ITEMS_QUOTA:raise CreateItemError('quota exceeded')return Item(name=name)try:item = create_item(name)print(f"Item {name} created")
except CreateItemError as e:print(f"Create item failed: {e}")
  • 优点
    • create_item() 只返回 Item 或抛出异常,调用方只用关注成功的情况,不需要额外判断错误码。
    • 代码更清晰,减少 if/else 嵌套。
    • 可以在更高层统一处理 CreateItemError,提高代码的可维护性。

总结

异常让函数返回值更稳定,不需要额外处理错误码。
异常自动向上传播,让调用方可以自由选择是否处理
但必须确保顶层有统一的异常处理,否则可能导致程序崩溃。

最佳实践:使用异常可以提高代码的可读性和可维护性,但一定要在系统入口处做好全局异常处理,防止程序意外崩溃。


create_item() 方法中如果执行了raise抛出异常,还会往后执行 return Item(name=name)么?

不会!

一旦 raise 语句被执行,函数会立即中断,不会继续执行后续代码。因此,如果 raise CreateItemError(...) 被触发,return Item(name=name) 永远不会执行


示例代码

python">def create_item(name):if len(name) > 10:raise ValueError("name too long")print("This line will be executed if no exception occurs.")return f"Item({name})"# 测试
try:create_item("short_name")  # 正常情况create_item("this_name_is_too_long")  # 触发异常
except ValueError as e:print(f"Caught exception: {e}")

运行结果

This line will be executed if no exception occurs.
Caught exception: name too long

说明

  1. 第一次调用 create_item("short_name"),没有触发异常,所以 print 语句执行了,return 也执行了。
  2. 第二次调用 create_item("this_name_is_too_long"),触发了 raise ValueError("name too long"),函数立即终止,return 语句不会执行

总结

  • raise 语句会立即终止函数的执行,抛出异常给调用者。
  • 如果 raise 被执行,后面的 return 语句就不会执行
  • 异常会向上传播,直到被 try-except 代码块捕获,否则程序会崩溃

http://www.ppmy.cn/devtools/158723.html

相关文章

vscode插件Remote - SSH使用教程

Remote - SSH 是一款非常实用的 Visual Studio Code (VSCode) 扩展插件,它允许开发者通过SSH连接到远程服务器,并像在本地一样进行代码编辑和调试。这意味着你可以直接在VS Code中打开位于远程机器上的文件夹,并利用本地安装的VS Code功能,如语法高亮、智能感知、Git集成等…

【Android开发AI实战】选择目标跟踪基于opencv实现——运动跟踪

文章目录 【Android 开发 AI 实战】选择目标跟踪基于 opencv 实现 —— 运动跟踪一、引言二、Android 开发与 AI 的融合趋势三、OpenCV 简介四、运动跟踪原理(一)光流法(二)卡尔曼滤波(三)粒子滤波 五、基于…

关于conda换镜像源,pip换源

目录 1. 查看当前下载源2. 添加镜像源2.1清华大学开源软件镜像站2.2上海交通大学开源镜像站2.3中国科学技术大学 3.删除镜像源4.删除所有镜像源,恢复默认5.什么是conda-forge6.pip换源 1. 查看当前下载源 conda config --show channels 如果发现多个 可以只保留1个…

B端产品思考:使用AI帮助B端产品经理

某一种类型B端产品经理的工作,大部分是建管理后台,提供一些工作流、业务支撑系统、数据管理系统。例如常见功能:项目管理、系统管理、数据管理;常见的操作:新增、编辑、删除、预览、下载。 适用于此类产品经理的一款A…

Grafana Windows在 Windows 上轻松实现数据监控与可视化

Grafana 是一个开源的监控和数据可视化平台,广泛用于展示和分析时间序列数据。它支持多种数据源,如 Prometheus、InfluxDB、Graphite、Elasticsearch 等,并提供了丰富的图表和仪表板功能,帮助用户直观地监控系统性能、应用程序状态…

掌握 PHP 单例模式:构建更高效的应用

在 PHP 应用开发中,资源的高效管理至关重要。单例模式是一种能够帮助我们实现这一目标的设计模式。本文将深入探讨单例模式的概念、工作原理以及在 PHP 项目中何时应该(或不应该)使用它。 什么是单例模式? 单例模式是一种设计模…

一文讲清前端热更新

​​​​​​ 引言 前端开发中,“保存代码后页面自动刷新”早已成为开发者的标配体验。但你是否思考过,为什么某些场景下修改代码后页面无需完全刷新,甚至能保留当前状态(如表单输入、滚动位置)?这背后的…

【数据结构基础_链表】

1、链表的定义 链表与数组的区分: 数组是一块连续的内存空间,有了这块内存空间的首地址,就能直接通过索引计算出任意位置的元素地址。 数组最大的优势是支持通过索引快速访问元素,而链表就不支持。链表不一样,一条链…