yield
yield 的核心作用:暂停与恢复#
普通 return: 函数执行 → 返回值 → 函数结束(内存释放)
yield: 函数执行 → 产出值 → 暂停等待 → 被唤醒后继续执行plaintext具体对比#
❌ 如果用 return(错误)#
def get_db():
db = "数据库连接"
return db # ← 函数到这里就结束了!
# 下面这行永远不会执行
db = "关闭连接" # ❌ 死代码,资源无法释放python结果: 数据库连接永远无法关闭,造成连接泄漏
✅ 用 yield(正确)#
def get_db():
db = "数据库连接"
try:
yield db # ← 暂停!产出值,但函数不结束
finally:
db = "关闭连接" # ← 路由结束后,从这里继续执行python执行流程可视化#
时间线 ─────────────────────────────────────────►
get_db() 开始
│
▼
db = "数据库连接" ◄── 创建资源
│
▼
yield db ◄── 【暂停点】产出值给路由函数
│ │
│ ▼
│ read_items(db=...) 执行中
│ │
│ ▼
│ 路由函数完成
│
▼ 【恢复执行】
finally:
db = "关闭连接" ◄── 清理资源(一定执行)plaintext关键特性:上下文保持#
def get_db():
db = create_expensive_connection() # 第1步:创建
print("连接已创建")
yield db # 第2步:交出控制权(暂停)
# ↓↓↓ 路由结束后,从这里继续 ↓↓↓
print("准备清理")
db.close() # 第3步:清理
print("连接已关闭")python输出顺序:
连接已创建 ← yield 之前
[路由函数执行中] ← yield 暂停期间
准备清理 ← 路由结束后恢复
连接已关闭 ← 最终清理plaintext类比理解#
| 类比 | 解释 |
|---|---|
| 游戏存档点 | yield = 存档,下次从存档点继续,不是从头开始 |
| 租借物品 | 借出(yield)→ 对方使用 → 归还后你做检查(finally) |
| 协程/生成器 | Python 生成器的基础机制,支持双向通信 |
配合 try...finally 的威力#
def get_db():
db = connect()
try:
yield db
# 如果路由函数正常完成,执行到这里
except Exception:
# 如果路由函数抛出异常,也能捕获
raise
finally:
db.close() # ✅ 无论成功/失败,100%执行python这是 Python 中资源管理的最佳实践模式,比 __enter__/__exit__ 上下文管理器更简洁。
一句话总结#
yield让函数变成”可暂停的”,使得 FastAPI 能在请求处理前后自动执行 setup/teardown 逻辑,实现声明式的资源生命周期管理。