7Learning Python(第5版)

异常与对象

异常处理

try/exceptraise自定义异常上下文管理器

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第7章:异常与对象(Exceptions and Objects)

一、导读

1.1 本章学习目标

第7章讲解 Python 的异常处理和高级对象特性。异常处理是编写健壮代码的关键。

1.2 为什么第七章如此重要

异常处理让程序能够优雅地应对错误。理解异常层次和最佳实践是专业 Python 开发者的必备技能。

1.3 核心问题引导

Python 的异常层次结构是什么?

如何正确使用 try/except?

自定义异常如何设计?

上下文管理器如何工作?


二、核心概念详解

7.1 异常层次

BaseException
├── SystemExit
├── KeyboardInterrupt
├── GeneratorExit
└── Exception
    ├── ArithmeticError
    │   ├── ZeroDivisionError
    │   └── OverflowError
    ├── AttributeError
    ├── ImportError
    ├── IndexError
    ├── KeyError
    ├── NameError
    ├── OSError
    │   ├── FileNotFoundError
    │   └── PermissionError
    ├── TypeError
    └── ValueError

7.2 异常处理最佳实践

python
# 只捕获特定异常
try:
    result = 10 / value
except ZeroDivisionError:
    print("Cannot divide by zero")
except TypeError as e:
    print(f"Type error: {e}")

# 使用 else 和 finally
try:
    f = open("file.txt")
except FileNotFoundError:
    print("File not found")
else:
    content = f.read()  # 没有异常时执行
finally:
    f.close()  # 总是执行

# 不要捕获所有异常
# 反模式
try:
    do_something()
except Exception:  # 太宽泛
    pass

# 正确做法
try:
    do_something()
except SpecificError as e:
    logger.error(f"Specific error: {e}")
    raise

7.3 自定义异常

python
class AppError(Exception):
    """应用基础异常"""
    pass

class ValidationError(AppError):
    """验证错误"""
    def __init__(self, field, message):
        self.field = field
        self.message = message
        super().__init__(f"Validation error on '{field}': {message}")

class NotFoundError(AppError):
    """资源未找到"""
    def __init__(self, resource, id):
        self.resource = resource
        self.id = id
        super().__init__(f"{resource} with id '{id}' not found")

# 使用
try:
    validate_user(data)
except ValidationError as e:
    print(f"Invalid {e.field}: {e.message}")

7.4 上下文管理器

python
# 使用 contextlib
from contextlib import contextmanager

@contextmanager
def timer(label):
    start = time.time()
    yield
    elapsed = time.time() - start
    print(f"{label}: {elapsed:.2f}s")

with timer("Operation"):
    time.sleep(1)

# 管理多个资源
from contextlib import ExitStack

with ExitStack() as stack:
    files = [stack.enter_context(open(f"f{i}.txt")) for i in range(5)]
    # 所有文件自动关闭

三、实战案例

7.1 异常链

python
class DatabaseError(AppError):
    pass

class UserRepository:
    def find_by_id(self, user_id):
        try:
            return self.db.query(f"SELECT * FROM users WHERE id = {user_id}")
        except ConnectionError as e:
            raise DatabaseError(f"Database connection failed") from e
        except Exception as e:
            raise DatabaseError(f"Query failed") from e

# 保留原始异常信息
try:
    user = repo.find_by_id(123)
except DatabaseError as e:
    print(f"Error: {e}")
    print(f"Cause: {e.__cause__}")

四、本章小结

Python 异常层次清晰。只捕获特定异常,使用异常链保留原始信息。自定义异常继承自 AppError。上下文管理器简化资源管理。


五、思考与练习

Python 的异常层次结构是什么?

如何正确使用 try/except/else/finally?

自定义异常如何设计?

异常链的作用是什么?

上下文管理器如何工作?


7/8异常与对
0%