练习题:72
目录
Python题目
题目
题目分析
需求理解
关键知识点
实现思路分析
复杂度分析
可能遇到的问题及注意事项
代码实现
代码解释
1. 自定义异常类的定义
2. 函数中抛出自定义异常
3. 调用函数并捕获异常
运行思路
1. 自定义异常类定义阶段
2. 函数定义阶段
3. 函数调用与异常捕获阶段
结束语
Python题目
题目
在函数中抛出一个自定义异常,并在调用函数的地方捕获该异常。
题目分析
需求理解
本题要求在 Python 里实现自定义异常的抛出与捕获。具体来说,需要定义一个自定义的异常类,然后在某个函数中根据特定条件抛出这个自定义异常,最后在调用该函数的代码部分使用 try - except
语句捕获这个异常,并进行相应的处理。这样做的好处是可以让程序在遇到特定问题时,抛出更具针对性的异常信息,方便开发者进行调试和维护。
关键知识点
- 自定义异常类:在 Python 中,自定义异常类需要继承自
Exception
类或其子类。通过继承,自定义异常类可以拥有异常的基本特性,并且可以根据需求添加额外的属性和方法。 - 异常抛出:使用
raise
关键字在函数内部抛出异常。当程序执行到raise
语句时,会立即停止当前的执行流程,并将异常向上抛出。 - 异常捕获:使用
try - except
语句来捕获并处理异常。try
块中放置可能会抛出异常的代码,except
块用于捕获特定类型的异常,并执行相应的处理逻辑。
实现思路分析
- 定义自定义异常类:创建一个新的类,继承自
Exception
类,作为自定义异常类。可以根据需要为该类添加初始化方法,用于传递异常信息。 - 定义函数并抛出异常:在函数中,根据特定的条件判断是否需要抛出自定义异常。如果条件满足,使用
raise
关键字抛出自定义异常实例。 - 调用函数并捕获异常:在调用函数的代码部分,使用
try - except
语句包裹函数调用。try
块中调用函数,except
块中捕获自定义异常,并进行相应的处理,如打印错误信息。
复杂度分析
- 时间复杂度:抛出和捕获异常的操作本身的时间复杂度为 \(O(1)\),因为它们只是改变程序的执行流程,不涉及大量的数据处理。
- 空间复杂度:异常对象的创建和处理通常只需要常数级的额外空间,因此空间复杂度也为 \(O(1)\)。
可能遇到的问题及注意事项
- 异常类的继承:确保自定义异常类正确继承自
Exception
类或其子类,否则可能无法被try - except
语句正确捕获。 - 异常信息的传递:在抛出异常时,可以传递相关的异常信息,方便在捕获异常时进行调试和错误处理。
- 异常类型的匹配:在
except
语句中,要准确指定要捕获的异常类型,确保能够捕获到抛出的自定义异常。
代码实现
# 定义自定义异常类,继承自 Exception 类
class CustomError(Exception):
def __init__(self, message):
# 调用父类 Exception 的构造函数,传入异常信息
super().__init__(message)
# 定义一个函数,根据条件抛出自定义异常
def check_number(num):
if num < 0:
# 当传入的数字小于 0 时,抛出自定义异常
raise CustomError("输入的数字不能为负数")
return num * 2
try:
# 调用函数,传入一个负数,触发异常
result = check_number(-5)
print(f"计算结果: {result}")
except CustomError as e:
# 捕获自定义异常,并打印异常信息
print(f"捕获到自定义异常: {e}")
代码解释
1. 自定义异常类的定义
class CustomError(Exception):
def __init__(self, message):
super().__init__(message)
CustomError
类继承自Exception
类,这使得它成为一个自定义的异常类。__init__
方法是构造函数,它接收一个message
参数,用于存储异常的详细信息。super().__init__(message)
调用了父类Exception
的构造函数,将message
传递给父类,以便在抛出异常时能够携带该信息。
2. 函数中抛出自定义异常
def check_number(num):
if num < 0:
raise CustomError("输入的数字不能为负数")
return num * 2
check_number
函数接收一个参数num
。- 在函数内部,使用
if
语句检查num
是否小于 0。如果是,则使用raise
关键字抛出自定义异常CustomError
,并传递异常信息"输入的数字不能为负数"
。 - 如果
num
不小于 0,则返回num
的两倍。
3. 调用函数并捕获异常
try:
result = check_number(-5)
print(f"计算结果: {result}")
except CustomError as e:
print(f"捕获到自定义异常: {e}")
try
块中调用check_number
函数,并传入一个负数-5
。由于传入的数字小于 0,函数会抛出自定义异常。except CustomError as e
用于捕获CustomError
类型的异常,并将异常对象赋值给变量e
。- 在
except
块中,打印捕获到的自定义异常的信息。
运行思路
1. 自定义异常类定义阶段
class CustomError(Exception):
def __init__(self, message):
super().__init__(message)
- 类的创建:Python 解释器执行到
class CustomError(Exception):
时,会创建一个名为CustomError
的类,并且让它继承自Exception
类。这意味着CustomError
具备了异常类的基本特性,能够被try - except
语句捕获。 - 构造函数定义:
__init__
方法是CustomError
类的构造函数,它接收一个参数message
,用于存储异常的详细信息。super().__init__(message)
调用了父类Exception
的构造函数,将传入的message
传递给父类,这样在抛出该异常时就能携带具体的错误信息。
2. 函数定义阶段
def check_number(num):
if num < 0:
raise CustomError("输入的数字不能为负数")
return num * 2
- 函数创建:解释器执行到
def check_number(num):
时,会创建一个名为check_number
的函数对象,该函数接收一个参数num
。 - 逻辑定义:函数内部有一个
if
条件判断,如果传入的num
小于 0,就会执行raise CustomError("输入的数字不能为负数")
语句。这会创建一个CustomError
异常实例,并将"输入的数字不能为负数"
作为异常信息存储在该实例中,然后立即停止函数的执行,将异常抛出。如果num
不小于 0,则函数会正常返回num
的两倍。
3. 函数调用与异常捕获阶段
try:
result = check_number(-5)
print(f"计算结果: {result}")
except CustomError as e:
print(f"捕获到自定义异常: {e}")
- 进入
try
块:程序执行到try
语句时,会开始执行try
块中的代码。首先调用check_number(-5)
函数,将-5
作为参数传递给check_number
函数。 - 函数内部处理:在
check_number
函数中,由于传入的-5
小于 0,满足if
条件,于是会抛出自定义异常CustomError("输入的数字不能为负数")
。 - 异常抛出与捕获:一旦抛出异常,程序会立即跳出
try
块,开始查找能够捕获该异常的except
块。由于抛出的是CustomError
类型的异常,而except CustomError as e:
正是用于捕获这种类型的异常,所以程序会进入这个except
块。 - 异常处理:在
except
块中,e
是捕获到的异常实例,通过print(f"捕获到自定义异常: {e}")
语句,会将异常信息"输入的数字不能为负数"
打印输出,从而完成了异常的捕获和处理。
综上所述,整个程序的运行流程是先定义自定义异常类和函数,然后在 try
块中调用函数,当函数内部满足特定条件时抛出自定义异常,最后在 except
块中捕获并处理该异常。
结束语
通过这次对自定义异常的实践,你深入掌握了 Python 中异常处理的高级应用技巧。从定义独特的自定义异常类,到在函数中灵活抛出异常,并在调用处精准捕获,每一步都让你对程序的健壮性和可控性有了更深刻的理解。
在实际的编程项目中,自定义异常是一种强大的工具,它能让你的程序在面对各种特殊情况时,以清晰、明确的方式传达错误信息,便于调试和维护。无论是处理数据验证错误、资源访问失败,还是其他特定的业务逻辑异常,自定义异常都能助你一臂之力。
编程是一个不断探索和积累的过程,异常处理只是其中的一个重要环节。希望你能保持对编程的热情和好奇心,继续挖掘 Python 的丰富功能,在解决复杂问题的过程中不断提升自己的编程能力,创造出更加稳定、可靠的代码。