- 上下文管理器 (@contextmanager)
将函数体一分为二,yield 前获取资源,yield 后释放资源。
点击查看代码
from contextlib import contextmanager
@contextmanager
def managed_resource():
print(">>> 获取资源")
resource = {"status": "connected"}
try:
yield resource # 暂停,将 resource 传给 with ... as var
finally:
print(">>> 释放资源") # 无论 with 块是否异常,必定执行
# 使用
with managed_resource() as r:
print(f"使用资源: {r}")
# 输出:
# >>> 获取资源
# 使用资源: {'status': 'connected'}
# >>> 释放资源
- 惰性生成器
按需产出值,不一次性加载全部数据到内存。
点击查看代码
def read_large_file(path):
with open(path) as f:
for line in f:
yield line.strip() # 每次只产出一行,内存占用恒定
# 消费时逐个获取,而非全部读入列表
for line in read_large_file("10GB_log.txt"):
process(line)
- 协程 / 双向通信 (send)
yield 既向外产出值,又接收外部传入的值。
点击查看代码
def accumulator():
total = 0
while True:
value = yield total # ① 产出 total;② 接收 send() 传入的 value
total += value
acc = accumulator()
next(acc) # 必须先 next() 启动,走到第一个 yield → 返回 0
print(acc.send(10)) # 传入 10, total=10 → 打印 10
print(acc.send(20)) # 传入 20, total=30 → 打印 30
- 委托生成器 (yield from)
将子生成器的产出和双向通信协议透明转发,消除嵌套循环。
点击查看代码
def flatten(nested):
for item in nested:
if isinstance(item, list):
yield from flatten(item) # 递归委托,自动透传 send/throw/close
else:
yield item
print(list(flatten([1, [2, [3, 4]], 5])))
# → [1, 2, 3, 4, 5]
- 类迭代协议 (iter)
在类的 iter 中使用 yield,让自定义对象直接支持 for 循环。
点击查看代码
class Range:
def __init__(self, start, stop):
self.start = start
self.stop = stop
def __iter__(self):
current = self.start
while current < self.stop:
yield current # 使实例可直接 for 循环,无需手写 __next__
current += 1
for n in Range(3, 7):
print(n) # 3, 4, 5, 6
| 用法 |
关键语法 |
数据流向 |
核心价值 |
典型场景 |
| 1. 上下文管理器 |
@contextmanager + yield |
单向产出(资源句柄) |
将函数体一分为二,前半部分获取资源(__enter__),后半部分释放资源(__exit__),保证清理逻辑必执行 |
SSH隧道、数据库连接、文件锁、临时环境变量切换 |
| 2. 惰性生成器 |
yield value |
单向产出 |
按需计算,内存复杂度从 O(n) 降为 O(1),支持无限序列 |
读取超大文件、流式API响应、数据管道(Pipeline) |
| 3. 协程(双向通信) |
var = yield value + .send() |
双向收发 |
函数可暂停并接收外部注入的值,实现协作式并发与状态保持 |
生产者-消费者模型、状态机、旧版异步框架(如Scrapy/Tornado) |
| 4. 委托生成器 |
yield from sub_gen |
双向透传 |
自动将子生成器的产出及 send()/throw()/close() 协议透明转发,消除嵌套循环 |
递归展平嵌套结构、组合多个数据源、asyncio底层实现 |
| 5. 类迭代协议 |
在 __iter__ 中 yield |
单向产出 |
替代繁琐的 __next__ + StopIteration 三件套,让自定义对象天然支持 for 循环且具备惰性 |
自定义集合类、树/图遍历、分页查询对象 |