上下文管理器是实现了 __enter__ / __exit__ 协议的对象,配合 with 语句保证"进入时获取资源、退出时必然释放",即使中途抛异常也会执行清理。with open(f) as fp 等价于:__enter__ 的返回值绑定到 as 变量,块结束或异常时调用 __exit__(exc_type, exc_val, exc_tb)__exit__ 返回 True 表示吞掉异常。

两种实现方式:

# 1. 类实现协议
class Timer:
    def __enter__(self):
        self.start = time.time()
        return self
    def __exit__(self, *exc):
        print("耗时:", time.time() - self.start)
        return False  # 不吞异常

# 2. contextlib 生成器写法,更简洁
from contextlib import contextmanager

@contextmanager
def timer():
    start = time.time()
    try:
        yield          # yield 前是 __enter__,后是 __exit__
    finally:
        print("耗时:", time.time() - start)

要点:yield 处若收到异常会被 throw 进生成器,所以要用 try/finally 包裹才能保证清理;@contextmanager 方式省样板但语义不变。常见应用:文件、锁、数据库事务、临时修改状态(decimal.localcontext、测试 mock 的 patch)。追问方向:__exit__ 返回值语义、异步上下文管理器 async with__aenter__/__aexit__ExitStack 动态管理多个上下文。