Python 实现自定义异常

在Python编程中,异常处理是保证程序健壮性的重要机制。Python提供了一些内置的异常类,如ValueErrorTypeErrorIndexError等,开发者可以直接使用这些类来捕获和处理程序运行中出现的各种错误。然而,某些场景下,内置的异常类型可能不足以描述特定的错误类型,这时候我们就需要定义自己的异常类,即自定义异常。

二、Python中的异常处理机制

在介绍自定义异常之前,我们先回顾一下Python的异常处理机制。异常处理主要包括以下几个关键字:

  1. try: 包含可能会引发异常的代码块。
  2. except: 捕获并处理异常的代码块。
  3. else: 当try代码块没有发生异常时执行的代码块。
  4. finally: 无论是否发生异常,都要执行的代码块。

举个简单的例子:

try:result = 10 / 0
except ZeroDivisionError as e:print("Error: Division by zero is not allowed.")
else:print("The result is:", result)
finally:print("Execution completed.")

上述代码会捕获到ZeroDivisionError异常,并输出错误信息。finally块中的代码会始终执行,无论是否发生异常。

三、为什么需要自定义异常?

尽管Python内置了丰富的异常类,但在某些情况下,这些异常类型可能不足以准确描述特定的业务逻辑错误。例如,在一个银行交易系统中,可能需要处理类似“余额不足”这样的情况。虽然可以使用ValueErrorRuntimeError等内置异常,但这并不能明确表达出错误的具体含义。此时,自定义异常就显得尤为重要,它可以使代码更加清晰、易读,并且能够更好地与业务逻辑匹配。

四、如何定义自定义异常?

自定义异常通常是从Python的内置异常类(如Exception)派生的子类。我们可以为自定义异常类添加一些额外的信息或方法,以增强其实用性。

以下是一个简单的自定义异常类的示例:

class InsufficientFundsError(Exception):def __init__(self, balance, amount):super().__init__(f"Attempt to withdraw {amount} with balance of {balance}")self.balance = balanceself.amount = amountdef __str__(self):return f"InsufficientFundsError: Cannot withdraw {self.amount} from a balance of {self.balance}"

在这个例子中,我们定义了一个名为InsufficientFundsError的异常类,用于在银行交易系统中处理余额不足的情况。这个异常类继承自Exception,并且重写了__init__方法,以接收余额和提取金额两个参数。在__str__方法中,我们自定义了异常的字符串表示形式,确保当异常被打印时能输出有意义的信息。

五、如何使用自定义异常?

自定义异常的使用方式与内置异常类似。以下是如何在实际代码中使用前面定义的InsufficientFundsError的示例:

class BankAccount:def __init__(self, balance):self.balance = balancedef withdraw(self, amount):if amount > self.balance:raise InsufficientFundsError(self.balance, amount)self.balance -= amountreturn self.balance# 示例使用
account = BankAccount(100)try:account.withdraw(150)
except InsufficientFundsError as e:print(e)
else:print(f"Withdrawal successful. New balance: {account.balance}")

在这个例子中,我们创建了一个BankAccount类,并实现了一个withdraw方法。如果用户尝试提取超过当前余额的金额,程序会抛出InsufficientFundsError异常。异常会被try-except块捕获并处理,输出相应的错误信息。

六、自定义异常的最佳实践

在定义和使用自定义异常时,有一些最佳实践可以帮助我们编写更健壮、更易于维护的代码。

1. 继承自适当的基类

虽然自定义异常通常直接继承自Exception类,但在某些情况下,继承自其他更具体的异常类可能更合适。例如,如果你正在编写一个网络相关的库,可能更适合从IOErrorOSError继承。

2. 命名规范

自定义异常的命名应遵循Python的命名规范,一般采用ErrorException作为后缀,例如InvalidTransactionErrorDataValidationException。这样可以直观地看出这是一个异常类。

3. 提供有用的信息

自定义异常类应该尽量提供尽可能多的上下文信息,这样当异常被捕获时,开发者可以更容易地诊断和修复问题。例如,可以在自定义异常的__init__方法中传入与错误相关的变量,并在__str__方法中格式化这些信息。

4. 避免过度使用自定义异常

虽然自定义异常可以帮助你更好地描述特定错误类型,但也不应滥用。在设计时,首先考虑是否有合适的内置异常可以使用,只有在确实需要表达特定业务逻辑错误时,才创建新的自定义异常类。

七、捕获和处理多个异常

在实际应用中,一个代码块可能会抛出多种类型的异常,特别是在涉及多个操作的情况下。我们可以通过多个except块来分别捕获和处理不同类型的异常。例如:

try:account.withdraw(150)account.withdraw('fifty')  # This will cause a TypeError
except InsufficientFundsError as e:print(e)
except TypeError as e:print("Error: Invalid amount type provided.")

在这个例子中,InsufficientFundsErrorTypeError分别被单独处理。通过这样设计,可以针对不同类型的错误执行不同的处理逻辑。

八、自定义异常的层次结构

在大型项目中,可能需要定义多个自定义异常,这些异常可能具有共同的父类。为此,可以设计一个异常层次结构。例如:

class TransactionError(Exception):"""所有交易相关异常的基类"""passclass InsufficientFundsError(TransactionError):def __init__(self, balance, amount):super().__init__(f"Attempt to withdraw {amount} with balance of {balance}")self.balance = balanceself.amount = amountclass UnauthorizedAccessError(TransactionError):def __init__(self, user):super().__init__(f"User {user} is not authorized for this transaction")self.user = user

在这个例子中,TransactionError是所有交易相关异常的基类,而InsufficientFundsErrorUnauthorizedAccessError分别继承自TransactionError。这种设计方式可以帮助我们在需要捕获所有交易相关异常时,只需捕获TransactionError即可,而无需单独处理每种异常。

九、使用自定义异常进行验证

自定义异常不仅可以用于处理运行时错误,还可以用于输入验证。例如:

class ValidationError(Exception):passdef validate_age(age):if age < 0:raise ValidationError("Age cannot be negative.")elif age > 120:raise ValidationError("Age cannot exceed 120.")return Truetry:validate_age(-5)
except ValidationError as e:print(e)

在这个例子中,validate_age函数用于验证用户输入的年龄是否合理,如果输入不合法,则抛出ValidationError。这种方法可以有效地将验证逻辑与业务逻辑分离。

自定义异常是增强代码可读性和维护性的有效工具,尤其是在处理复杂业务逻辑时。掌握这一技术不仅能提高代码的健壮性,还能使错误处理逻辑更加清晰明了。

在实际开发中,自定义异常应根据具体需求谨慎使用,避免过度设计。同时,通过合理的异常层次结构和详细的异常信息,能够帮助我们更好地调试和维护代码。

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

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

相关文章

无人机使用材料与结构特点详解,看完这篇文你就懂了!!!

一、常用材料 无人机的常用材料主要包括机身材料&#xff08;结构材料和非结构材料&#xff09;、发动机材料和涂料&#xff0c;其中最主要的是机身结构材料和发动机材料。 机身结构材料 低速无人机&#xff1a;主要使用木材、塑料、玻璃纤维或碳纤维复合材料蜂窝夹层结构。…

SQL Server数据库查询常用语句汇总

这里&#xff0c;汇总了在使用SQL Server数据库的过程中经常会写的查询语句。 情形1 根据时间查询最新一条数据 &#xff08;dtime类型为datetime&#xff09; select top 1 名称 as name,列名1 as parname1,列名2 as parname2,dtime,col1,col2 from demo order by dtime …

【基础算法总结】多源 BFS_多源最短路问题

多源 BFS_多源最短路问题 1.多源 BFS_多源最短路问题2.01 矩阵3.飞地的数量4.地图中的最高点5.地图分析 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496; 你的支持是对我最大的鼓励&#xff0c;我们一起努力吧!&#x1f603;&…

NtripShare全站仪自动化监测之气象改正

最近有幸和自动化监测领域权威专家进行交流&#xff0c;讨论到全站仪气象改正的问题&#xff0c;因为有些观点与专家不太一致&#xff0c;所以再次温习了一下全站仪气象改正的技术细节。 气象改正的概念 全站仪一般利用光波进行测距&#xff0c;首先仪器会处理测距光波的相位漂…

SpingBoot 两种方式配置多数据源

第一种&#xff1a;使用与MyBaits-Plus师出同门的“dynamic-datasource-spring-boot-starter” 官网地址&#xff1a; 基础必读&#xff08;免费&#xff09; dynamic-datasource 看云 1&#xff1a;引入依赖 <!-- 苞米豆多数据源 --> <dependency><group…

科技大厂对AI的垄断

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

ios白苹果修复办法有哪些?

在这个数字化时代&#xff0c;iPhone作为智能手机的佼佼者&#xff0c;早已融入了我们生活的方方面面。然而&#xff0c;当那熟悉的开机画面——“白苹果”意外地成为了你的日常&#xff0c;无疑让人头疼不已。别担心&#xff0c;今天我们就来聊聊iOS白苹果现象的成因及几种有效…

C#实现数据采集系统-多设备采集

系统功能升级-多设备采集 数据采集系统在网络环境下&#xff0c;性能足够&#xff0c;可以实现1对多采集&#xff0c;需要支持多个设备进行同时采集功能&#xff0c;现在就开发多设备采集功能 修改多设备配置 设备配置 将DeviceLink 改成List集合的DeviceLinks删掉Points&a…

运维开发——局域网SSH访问服务器与应用

摘要 本博文主要介绍局域网SSH访问登陆虚拟机和及其应用相关配置操作。 1. 局域网SSH访问登陆虚拟机 目标&#xff1a;在局域网内A电脑使用SSH登陆B电脑上虚拟机的服务器。 前提条件:B电脑为宿主机&#xff0c;可以正常使用ssh访问虚拟机服务器&#xff0c;虚拟机网络连接方…

数学强化| 李林880重点题速刷计划

快9月了&#xff0c;有的同学还没开始强化&#xff0c;进度确实有点慢了&#xff0c;有同学问&#xff1a; 刚开始强化&#xff0c;880题该如何快速刷完&#xff1f; 听我说&#xff0c;别急&#xff01;越是强化开始的晚&#xff0c;就越不能急&#xff0c;因为强化的作用有两…

【Datawhale AI 夏令营】第四期 基于2B源大模型 微调

定位&#xff1a;代码复现贴 教程&#xff1a;https://datawhaler.feishu.cn/wiki/PLCHwQ8pai12rEkPzDqcufWKnDd 模型加载 model AutoModelForCausalLM.from_pretrained(path, device_map"auto", torch_dtypetorch.bfloat16, trust_remote_codeTrue )AutoModelForC…

AI学习记录 - 如何快速构造一个简单的token词汇表

创作不易&#xff0c;有用的话点个赞 先直接贴代码&#xff0c;我们再慢慢分析&#xff0c;代码来自openai的图像分类模型的一小段 def bytes_to_unicode():"""Returns list of utf-8 byte and a corresponding list of unicode strings.The reversible bpe c…

压测工具哪个好?LoadRunner、Jmeter、Locust、Wrk 全方位对比....

当你想做性能测试的时候&#xff0c;你会选择什么样的测试工具呢&#xff1f;是会选择wrk&#xff1f;jmeter&#xff1f;locust&#xff1f;还是loadrunner呢&#xff1f;今天&#xff0c;笔者将根据自己使用经验&#xff0c;针对jmeter、locust、wrk和loadrunner常用的性能测…

前后端部署-服务器linux中部署Node.js环境

一.安装分布式版本管理系统Git (Alibaba Cloud Linux 3/2、CentOS 7.x) sudo yum install git -y 二.使用Git将NVM的源码克隆到本地的~/.nvm目录下&#xff0c;并检查最新版本。 git clone https://gitee.com/mirrors/nvm.git ~/.nvm && cd ~/.nvm && gi…

RVG29;狂犬病病毒肽;狂犬病病毒糖蛋白;115136-25-9;YTIWMPENPRPGTPCDIFTNSRGKRASNG

【RVG29 简介】 RVG29&#xff08;狂犬病病毒肽&#xff09;是一种由29个氨基酸组成的细胞穿透肽&#xff0c;它来源于狂犬病病毒糖蛋白。RVG肽能够特异性识别并结合中枢神经系统中普遍存在的烟碱型乙酰胆碱受体&#xff08;nAChR&#xff09;&#xff0c;并通过受体介导的转胞…

AR 眼镜之-系统应用音效-实现方案

目录 &#x1f4c2; 前言 AR 眼镜系统版本 系统应用音效 1. &#x1f531; 技术方案 1.1 技术方案概述 1.2 实现方案 1&#xff09;初始化 2&#xff09;播放音效 3&#xff09;释放资源 2. &#x1f4a0; 播放音效 2.1 静音不播放 2.2 获取音效默认音量 3. ⚛️ …

2.初识springcloud

文章目录 1.什么是SpringCloud1.1版本的介绍 2.Spring Cloud实现方案3.环境搭建4.服务拆分原则5.数据准备5.1订单服务5.2商品服务 大家好&#xff0c;我是晓星航。今天为大家带来的是 初识springcloud 相关的讲解&#xff01;&#x1f600; 1.什么是SpringCloud 简单来说&…

【算法基础实验】图论-最小生成树-Prim的即时实现

理论知识 Prim算法是一种用于计算加权无向图的最小生成树&#xff08;MST, Minimum Spanning Tree&#xff09;的贪心算法。最小生成树是一个连通的无向图的子图&#xff0c;它包含所有的顶点且总权重最小。Prim算法从一个起始顶点开始&#xff0c;不断将权重最小的边加入生成…

Excel表格添加趋势线_数据拟合

一个曲线通过补偿算法拟合为另一个曲线&#xff0c;通常可以通过多种数学和计算技术实现。这里也可以通过Excel表格添加趋势线&#xff0c;然后对趋势线进行拟合&#xff0c;得到趋势预测公式来达到数据补偿。 通过把你需要的数据导入到Excel表格中。 通过 “ 插入 ” --> “…

谷歌云AI新作:CROME,跨模态适配器高效多模态大语言模型

CROME: Cross-Modal Adapters for Efficient Multimodal LLM https://arxiv.org/pdf/2408.06610 Abstract 研究对象&#xff1a;Multimodal Large Language Models (MLLMs) demonstrate remarkable imagelanguage capabilities, but their widespread use faces challenges in…