Python异常类型的使用及说明
目录
- 一、异常的基本层次结构
- 二、主要异常类型详解
- 类别1:最常见的运行时错误
- 类别2:用于程序设计和逻辑控制的异常
- 类别3:与外部环境交互的错误
- 类别4:算术和导入错误
- 类别5:语法错误(特殊情况)
- 三、创建你自己的自定义异常
- 总结
在python中,我们可以 raise
的 Error(更准确地说是 Exception,异常)类型非常丰富,它们构成了一个清晰的类层次结构。了解这些类型及其用途,对于编写健壮、可读性强的代码至关重要。
NotImplementedError
是一个非常好的例子,它代表了一种特定的&jsldquo;设计意图”,而不仅仅是运行时错误。
下面我将为您详细介绍Python中可以 raise
的主要异常类型,并按照它们的逻辑关系和用途进行分类。
一、异常的基本层次结构
所有Python的内置异常都继承自 BaseException
类。这个层次结构非常重要:
BaseException ├── SystemExit ├── KeyboardInterrupt └── Exception <-- 绝大多数异常都继承自这里 ├── StopIteration ├── ArithmeticError │ ├── ZeroDivisionError │ └── OverflowError ├── AssertionError ├── AttributeError ├── ImportError │ └── ModuleNotFoundError ├── LookupError │ ├── IndexError │ └── KeyError ├── NameError ├── OSError │ ├── FileNotFoundError │ └── PermissionError ├── RuntimeError │ └── NotImplementedError <-- 你提到的在这里 ├── TypeError ├── ValueError └── ...等等
一条黄金法则:
在你的 try...except
语句中,通常应该捕获 Exception
或其子类,而不是 BaseException
。因为 SystemExit
和 KeyboardInterrupt
不被认为是程序“错误”,捕获它们会阻止程序正常退出或响应用户中断(Ctrl+C)。
二、主要异常类型详解
我将它们分为几类,以便更好地理解它们的用途。
类别1:最常见的运行时错误
这些是你在日常编程中遇到最多的错误。
ValueError
- 何时使用:当一个函数的参数类型正确,但其值不合适时。
- 示例:
int('abc')
。字符串'abc'
是一个str
类型,int()
可编程客栈以接受str
,但'abc'
这个值无法被转换成整数。
TypeError
- 何时使用:当对一个对象执行了其类型不支持的操作时。
- 示例:
'hello' + 5
。你不能将一个字符串和一个整数相加。
NameError
- 何时使用:DJIbm当尝试使用一个未被定义的变量名时。
- 示例:
print(my_undefined_variable)
。
IndexError
- 何时使用:当试图访问序列(如列表、元组)中一个不存在的索引时。
- 示例:
my_list = [1, 2, 3]; print(my_list[5])
。
KeyError
- 何时使用:当试图访问字典中一个不存在的键时。
- 示例:
my_dict = {'a': 1}; print(my_dict['b'])
。
AttributeError
- 何时使用:当试图访问或赋值一个对象不存在的属性或方法时。
- 示例:
my_int = 5; my_int.append(6)
。整数没有append
方法。
类别2:用于程序设计和逻辑控制的异常
这类异常通常由程序员主动 raise
,以表明某种设计上的约定或状态。
NotImplementedError
(继承自 RuntimeError
)
- 何时使用:在父类(尤其是抽象基类)中定义一个方法,并强制要求所有子类必须重写(实现)这个方法。它清楚地告诉其他开发者:“这个功能需要你自己去实现”。
示例:
class Shape: def get_area(self): # 任何继承自Shape的子类都必须实现自己的get_area方法 raise NotImplementedError("Subclasses must implement this method!") class Square(Shape): def __init__(self, side): self.side = side # 如果不写下面的方法,调用 get_area() 就会报错 def get_area(self): return self.side ** 2 # s = Shape() # s.get_area() # 这会立即引发 NotImplementedError sq = Square(5) print(sq.get_area()) # 输出 25
AssertionError
- 何时使用:当
assert
语句的条件为False
时被触发。它主要用于内部自检和调试,检查程序在某个点的状态是否符合预期。它不应该用于验证用户输入。
示例:
def process_data(data): assert isinstance(data, list), "Input data must be a list" # ... 后续处理 ... process_data("not a list") # 引发 AssertionError: Input data must be a list
RuntimeError
- 何时使用:当发生一个不属于任何其他明确类别的错误时。它是一个比较通用的错误,通常表示发生了某些意想不到的外部事件。
NotImplementedError
就是它的一个子类。
类别3:与外部环境交互的错误
OSError
- 何时使用:当发生系统相关的错误时,例如I/O操作失败。它是一个广泛的基类。
它的重要子类包括:
FileNotFoundError
: 试图打开一个不存在的文件。open('non_existent_file.txt')
。PermissionError
: 试图以没有权限的方式读写文件。例如,试图写入一个只读文件。ConnectionError
: 与网络连接相关的问题,如连接被拒绝 (ConnectionRefusedError
)。TimeoutError
: 一个操作在指定时间内未能完成。
类别4:算术和导入错误
ArithmeticError
- 何时使用:所有数值计算错误的基类。
子类包括:
ZeroDivisionError
: 除以零。1 / 0
。OverflowError
: 计算结果超出了数字类型能表示的最大范围。import math; math.exp(1000)
。
ImportError
- 何时使用:当
import
语句无法找到或加载模块时。 ModuleNotFoundError
(自 Python 3.6 起):是ImportError
的一个子类,更明确地表示模块本身未找到。- 示例:
import some_module_that_does_not_exist
。
类别5:语法错误(特殊情况)
SyntaxError
- 何时发生:这是你在运行代码之前就会遇到的错误。Python解释器在解析代码时发现语法不正确。你不能在DJIbm
try...except
块中捕获它,因为它在代码执行前就失败了。 IndentationError
(子类):最常见的语法错误之一,代码缩进不正确。
三、创建你自己的自定义异常
当内置的异常类型无法精确描述你的应用程序特有的错误时,最佳实践是创建自己的异常类。这能让你的代码更具可读性和可维护性。
自定义异常应该继承自 Exception
或其某个合适的子类。
示例:假设你在开发一个与外部API交互的应用。
# 1. 创建一个基础的自定义异常类 class MyAppError(Exception): """应用程序所有自定义异常的基类。""" pass # 2. 创建更具体的异常类 class APIResponseError(MyAppError): """当API返回一个意外的或错误的响应时引发。""" def __init__(self, message, status_code): super().__init__(message) self.status_code = status_code # 3. 在代码中使用它 def get_user_data(user_id): # response = requests.get(f"https://api.example.com/users/{user_id}") # 模拟一个失败的响应 status_code = 500 if status_code != 200: raise APIResponseError(f"Failed to fetch data, API returned {status_code}", status_code) # return response.json() # 4. 捕获它 try: get_user_data(123) except APIResponseError as e: print(f"Error communicating with API: {e}") print(f"Status code was: {e.status_code}") except MyAppError as e: print(f"An application-specific error occurred: {e}")
总结
使用 内置异常 来表示通用的编程错误(如 ValueError
, TypeError
)。
使用 NotImplementedError
来定义接口和抽象方法,强制子类实现。
使用 AssertionError
进行内部调试和状态检查。
当内置异常不足以描述你的特定问题域时,创建自定义异常,以提高代码的清晰度和健壮性。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)python。
精彩评论