Skip to content

闭包、装饰器原理与最佳实践

本章讲解 Python 装饰器与闭包的完整知识体系,从函数是一等公民到生产环境装饰器最佳实践。


快速开始

bash
# 进入示例项目
cd decorators_demo

# 安装依赖
uv sync

# 启动 Web 服务(ch03-ch06 章节演示)
uv run uvicorn app.main:app --reload
# → 访问 http://localhost:8000/docs 查看交互式 API 文档

# 运行测试(所有章节验证)
uv run pytest -v

知识地图

函数是一等公民 ──→ 闭包与作用域 ──→ 装饰器核心原理 ──→ 带参数装饰器
      ↓                   ↓                  ↓                    ↓
  函数传递能力       LEGB + nonlocal    @语法 + wraps      三层嵌套 + 工厂
  Callable 类型      闭包内存模型       定义时 vs 调用时    装饰器兼容性
        │                   │                  │                    │
        └───────────────────┴──────────────────┴────────────────────┘

                     functools 标准装饰器 ──→ 装饰器高级用法 ──→ 边界情况与调试
                                 ↓                        ↓                  ↓
                             lru_cache / cache         ParamSpec         叠加顺序问题
                             cached_property           async 装饰器      闭包陷阱排查
                             singledispatch            wrapt 库          调试工具函数
                             partial                   调试技巧          生产排查清单

章节导航

章节文件主题验证方式
01函数是一等公民函数传递 + Callablepytest tests/test_ch01.py
02闭包与作用域链LEGB + nonlocal + 闭包原理pytest tests/test_ch02.py
03装饰器核心原理@语法 + wraps + 执行时序curl localhost:8000/api/v1/demo
04带参数装饰器三层嵌套 + 工厂模式curl localhost:8000/api/v1/auth
05[functools 标准装饰器](./05-functools 标准装饰器.md)lru_cache/cached_propertycurl localhost:8000/api/v1/cache
06装饰器高级用法async + 类型精化 + wraptcurl localhost:8000/api/v1/async
07边界情况与调试实战叠加顺序 + 闭包陷阱 + 调试工具curl localhost:8000/api/v1/debug

API 端点一览

启动服务后,以下端点可用:

端点章节说明
GET /api/v1/demo/helloch03日志 + 计时装饰器演示
GET /api/v1/demo/wraps-comparisonch03@wraps 对比
GET /api/v1/auth/profilech04权限验证(user 角色)
DELETE /api/v1/auth/users/:idch04权限验证(admin 角色)
POST /api/v1/retry/fetchch04重试机制演示
GET /api/v1/cache/fibonacci/:nch05lru_cache 性能对比
GET /api/v1/cache/config/:keych05缓存命中率监控
GET /api/v1/async/call/{delay}ch06异步装饰器
GET /api/v1/async/sync/:delaych06同步操作对比
GET /api/v1/async/count-callsch06类装饰器计数
GET /api/v1/debug/order-conflictch07装饰器叠加顺序
GET /api/v1/debug/closure-trapch07循环变量陷阱
GET /api/v1/debug/async-await-missingch07async await 遗漏
GET /api/v1/debug/signature-lostch07函数签名丢失
GET /api/v1/debug/stack-swallowedch07异常栈被吞掉
GET /api/v1/debug/log-trackingch07生产日志追踪问题
GET /api/v1/debug/performance-analysisch07性能瓶颈追踪
POST /api/v1/debug/locate-errorch07装饰器链错误定位
GET /api/v1/debug/combined-decoratorch07组合装饰器演示

装饰器最佳实践清单

  1. 始终使用 @wraps — 保留原函数元信息
  2. 一个装饰器只做一件事 — 保持简单和可组合
  3. 用 ParamSpec 保留类型签名 — 让 IDE 提供更好的提示
  4. async 装饰器记得 await — 否则返回 coroutine 而非结果
  5. 优先用 functools 标准装饰器 — lru_cache, singledispatch 等
  6. 装饰器在定义时执行 — 不是调用时