一、生成器概述
生成器(Generator)是Python中用于创建迭代器的工具,通过yield
关键字实现。与普通函数不同,生成器函数返回的是迭代器对象,具有以下核心特性:
-
内存效率:只在需要时生成值,适合处理大数据流
-
状态保持:自动保存执行上下文
-
惰性计算:按需生成元素,节省计算资源
# 普通函数 vs 生成器函数
def normal_func():
return [x for x in range(1000000)] # 立即创建百万元素列表
def generator_func():
for x in range(1000000):
yield x # 每次只生成一个元素
二、生成器基础用法
1. 创建生成器
def simple_generator():
print("启动生成器")
yield 1
yield 2
yield 3
gen = simple_generator() # 创建生成器对象
print(type(gen)) # <class 'generator'>
2. 使用生成器
# 手动迭代
print(next(gen)) # 输出:启动生成器 1
print(next(gen)) # 2
print(next(gen)) # 3
# 自动迭代
for num in simple_generator():
print(num) # 依次输出1,2,3
三、执行流程解析
通过调试模式观察执行流程:
def countdown(n):
print("开始倒计时")
while n > 0:
yield n
n -= 1
print("发射!")
cd = countdown(3)
print(next(cd)) # 输出:开始倒计时 3
print(next(cd)) # 2
print(next(cd)) # 1
print(next(cd)) # 抛出StopIteration并打印"发射!"
执行流程图解:
首次next() → 执行到第一个yield暂停
↓
后续next() → 从上个yield之后继续执行到下一个yield
↓
循环直到函数结束,抛出StopIteration
四、高级应用技巧
1. 生成器表达式
squares = (x**2 for x in range(10))
print(sum(squares)) # 285
2. 双向通信
def interactive_gen():
total = 0
while True:
value = yield total # 接收外部传入值
if value is None:
break
total += value
ig = interactive_gen()
next(ig) # 启动生成器
print(ig.send(10)) # 10
print(ig.send(20)) # 30
3. 异常处理
def safe_gen():
try:
yield 1
yield 2
except ValueError:
yield "错误处理"
sg = safe_gen()
print(next(sg)) # 1
sg.throw(ValueError) # 输出:错误处理
4. 组合生成器
def chain_generators(*iterables):
for it in iterables:
yield from it # Python 3.3+语法
for num in chain_generators(range(3), (5,6)):
print(num) # 输出0,1,2,5,6
五、典型应用场景
1. 大文件处理
def read_large_file(file_path):
with open(file_path, 'r') as f:
while True:
chunk = f.read(4096)
if not chunk:
break
yield chunk
2. 无限序列
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
fib = fibonacci()
print([next(fib) for _ in range(10)]) # [0,1,1,2,3,5,8,13,21,34]
3. 状态机实现
def traffic_light():
states = ['RED', 'GREEN', 'YELLOW']
index = 0
while True:
yield states[index]
index = (index + 1) % 3
light = traffic_light()
print(next(light)) # RED
print(next(light)) # GREEN
六、注意事项
- 单次使用性:
gen = (x for x in range(3))
print(list(gen)) # [0,1,2]
print(list(gen)) # []
- 上下文管理器:
from contextlib import contextmanager
@contextmanager
def gen_context():
print("进入上下文")
try:
yield "资源"
finally:
print("清理资源")
with gen_context() as res:
print(f"正在使用 {res}") # 进入上下文 → 正在使用资源 → 清理资源
- 性能对比(数据量=1,000,000):
列表推导式:内存占用 82MB,耗时 0.1s
生成器表达式:内存占用 <1MB,耗时 0.08s
七、总结与建议
核心优势:
-
内存友好型数据处理
-
支持惰性求值
-
简化迭代器实现
-
实现协程基础
学习建议:
-
从简单计数器开始练习
-
尝试改写现有列表处理代码为生成器版本
-
探索
itertools
模块的生成器工具 -
学习异步编程时结合async/await语法
进阶路线:
生成器 → 迭代器协议 → 协程 → 异步IO
# 综合示例:分页查询生成器
def paginated_query(query):
page = 1
while True:
results = get_results(query, page)
if not results:
break
yield from results
page += 1
# 使用示例
for record in paginated_query("SELECT * FROM big_table"):
process(record)