第76集:生成器函数
学习目标
- 理解生成器函数的概念和作用
- 掌握yield关键字的使用
- 学会创建生成器函数
- 理解生成器函数与普通函数的区别
- 掌握生成器的执行流程
- 学会使用yield from语句
- 了解生成器的应用场景
什么是生成器函数
生成器函数(Generator Function)是一种特殊的函数,使用yield关键字来生成值。当调用生成器函数时,它不会立即执行函数体,而是返回一个生成器对象。
生成器函数的特点
- 使用
yield关键字而不是return - 每次调用
next()时执行到yield语句 - 保存执行状态,可以暂停和恢复
- 自动实现迭代器协议
- 内存效率高,惰性求值
基本语法
语法结构
def generator_function():
yield value1
yield value2
# ...与普通函数的对比
# 普通函数
def normal_function():
return [1, 2, 3]
# 生成器函数
def generator_function():
yield 1
yield 2
yield 3基本示例
示例1:简单生成器函数
def simple_generator():
"""简单的生成器函数"""
yield 1
yield 2
yield 3
# 创建生成器
gen = simple_generator()
# 获取值
print(next(gen)) # 1
print(next(gen)) # 2
print(next(gen)) # 3示例2:使用for循环遍历
def simple_generator():
yield 1
yield 2
yield 3
# 使用for循环
for num in simple_generator():
print(num)示例3:带参数的生成器函数
def count_generator(n):
"""生成0到n-1的数字"""
for i in range(n):
yield i
# 使用生成器
for num in count_generator(5):
print(num)生成器的执行流程
执行机制
def execution_demo():
print("开始执行")
yield 1
print("继续执行")
yield 2
print("再次执行")
yield 3
print("执行结束")
# 创建生成器
gen = execution_demo()
# 第一次调用next()
print("第一次next():")
result = next(gen) # 输出: 开始执行
print(f"返回值: {result}") # 返回值: 1
# 第二次调用next()
print("\n第二次next():")
result = next(gen) # 输出: 继续执行
print(f"返回值: {result}") # 返回值: 2
# 第三次调用next()
print("\n第三次next():")
result = next(gen) # 输出: 再次执行
print(f"返回值: {result}") # 返回值: 3执行流程图
- 调用生成器函数,返回生成器对象(不执行函数体)
- 第一次调用
next(),开始执行函数体,遇到yield暂停 - 第二次调用
next(),从上次暂停处继续执行,遇到下一个yield暂停 - 重复步骤3,直到函数结束或遇到
return - 函数结束时抛出
StopIteration异常
yield vs return
区别对比
# 使用return的函数
def return_function():
return [1, 2, 3]
return [4, 5, 6] # 永远不会执行
# 使用yield的生成器函数
def yield_function():
yield 1
yield 2
yield 3
yield 4
yield 5
yield 6关键区别
| 特性 | return | yield |
|---|---|---|
| 执行次数 | 一次 | 多次 |
| 返回值 | 单个值或对象 | 多个值(逐个生成) |
| 函数状态 | 不保存 | 保存 |
| 内存使用 | 一次性生成 | 惰性生成 |
生成器函数的应用
应用1:斐波那契数列
def fibonacci(n):
"""生成前n个斐波那契数"""
a, b = 0, 1
for _ in range(n):
yield a
a, b = b, a + b
# 使用斐波那契生成器
for num in fibonacci(10):
print(num)应用2:无限序列
def infinite_counter(start=0):
"""无限计数器"""
while True:
yield start
start += 1
# 使用无限计数器(需要手动停止)
counter = infinite_counter()
for i, num in enumerate(counter):
print(num)
if i >= 10:
break应用3:逐行读取文件
def read_file_lines(filename):
"""逐行读取文件"""
with open(filename, 'r', encoding='utf-8') as f:
for line in f:
yield line.strip()
# 使用文件行生成器
for line in read_file_lines('example.txt'):
print(line)应用4:数据批处理
def batch_processor(data, batch_size):
"""将数据分批处理"""
for i in range(0, len(data), batch_size):
yield data[i:i + batch_size]
# 使用批处理生成器
data = list(range(20))
for batch in batch_processor(data, 5):
print(f"批次: {batch}")yield from 语句
基本语法
def sub_generator():
yield 1
yield 2
def main_generator():
yield from sub_generator()
yield 3示例5:使用yield from
def sub_generator():
"""子生成器"""
yield "A"
yield "B"
yield "C"
def main_generator():
"""主生成器"""
yield from sub_generator()
yield "D"
yield "E"
# 使用生成器
for item in main_generator():
print(item)
# 输出: A, B, C, D, E示例6:嵌套生成器
def flatten(nested_list):
"""展平嵌套列表"""
for item in nested_list:
if isinstance(item, list):
yield from flatten(item)
else:
yield item
# 使用展平生成器
nested = [1, [2, 3], [4, [5, 6]], 7]
for item in flatten(nested):
print(item)
# 输出: 1, 2, 3, 4, 5, 6, 7生成器的高级用法
示例7:带状态的生成器
def stateful_generator():
"""带状态的生成器"""
state = 0
while True:
received = yield state
if received is not None:
state = received
else:
state += 1
# 使用带状态的生成器
gen = stateful_generator()
print(next(gen)) # 0
print(next(gen)) # 1
print(gen.send(10)) # 10
print(next(gen)) # 11示例8:管道处理
def source():
"""数据源"""
for i in range(10):
yield i
def filter_even(numbers):
"""过滤偶数"""
for num in numbers:
if num % 2 == 0:
yield num
def square(numbers):
"""平方"""
for num in numbers:
yield num ** 2
# 使用管道处理
pipeline = square(filter_even(source()))
for result in pipeline:
print(result)示例9:生成器表达式转生成器函数
# 生成器表达式
gen_exp = (x ** 2 for x in range(10))
# 等价的生成器函数
def gen_func():
for x in range(10):
yield x ** 2生成器的优势
优势1:内存效率
# 列表方式 - 占用大量内存
def get_squares_list(n):
return [x ** 2 for x in range(n)]
# 生成器方式 - 内存占用小
def get_squares_generator(n):
for x in range(n):
yield x ** 2优势2:惰性求值
def lazy_evaluation():
"""惰性求值示例"""
print("生成第一个值")
yield 1
print("生成第二个值")
yield 2
print("生成第三个值")
yield 3
# 只在需要时才计算
gen = lazy_evaluation()
print("创建生成器")
next(gen) # 此时才输出: 生成第一个值优势3:无限序列
def infinite_sequence():
"""无限序列"""
num = 0
while True:
yield num
num += 1
# 可以生成无限多个值
gen = infinite_sequence()
for i in range(5):
print(next(gen))生成器的限制
限制1:只能遍历一次
def my_generator():
yield 1
yield 2
yield 3
gen = my_generator()
# 第一次遍历
for num in gen:
print(num)
# 第二次遍历 - 不会输出
for num in gen:
print(num)限制2:不能回退
def my_generator():
yield 1
yield 2
yield 3
gen = my_generator()
next(gen) # 1
next(gen) # 2
# 无法回到1最佳实践
实践1:大数据处理使用生成器
# 推荐:使用生成器处理大数据
def process_large_data(data):
for item in data:
processed = transform(item)
yield processed
# 不推荐:使用列表
def process_large_data(data):
result = []
for item in data:
processed = transform(item)
result.append(processed)
return result实践2:使用yield from简化代码
# 推荐:使用yield from
def main_generator():
yield from sub_generator()
# 不推荐:手动遍历
def main_generator():
for item in sub_generator():
yield item实践3:生成器函数命名
# 推荐:生成器函数名包含"generator"或使用复数形式
def numbers_generator():
yield 1
yield 2
def get_numbers():
yield 1
yield 2实践4:正确处理StopIteration
def safe_generator():
"""安全的生成器"""
try:
yield 1
yield 2
yield 3
except GeneratorExit:
print("生成器被关闭")常见错误
错误1:在生成器中使用return
# 错误:在生成器中使用return返回值
def bad_generator():
yield 1
yield 2
return [3, 4, 5] # 这个值不会被返回
# 正确:使用yield返回所有值
def good_generator():
yield 1
yield 2
yield 3
yield 4
yield 5错误2:忘记yield关键字
# 错误:忘记yield关键字
def not_a_generator():
for i in range(10):
print(i)
# 正确:使用yield
def is_a_generator():
for i in range(10):
yield i错误3:在生成器中使用break
# 错误:在生成器中使用break
def bad_generator():
for i in range(10):
if i > 5:
break # 生成器会提前结束
yield i
# 正确:使用return或条件判断
def good_generator():
for i in range(10):
if i <= 5:
yield i性能优化
优化1:避免不必要的计算
# 优化前:计算所有值
def all_squares(n):
return [x ** 2 for x in range(n)]
# 优化后:按需计算
def lazy_squares(n):
for x in range(n):
yield x ** 2优化2:使用生成器表达式
# 优化前:使用生成器函数
def simple_gen(n):
for x in range(n):
yield x
# 优化后:使用生成器表达式
simple_gen = (x for x in range(n))总结
生成器函数是Python中强大的工具,具有以下特点:
核心概念
- 使用
yield关键字生成值 - 保存执行状态,可以暂停和恢复
- 自动实现迭代器协议
- 惰性求值,按需生成值
优势
- 内存效率高
- 适合处理大数据
- 可以生成无限序列
- 代码简洁优雅
应用场景
- 大数据处理
- 流式处理
- 无限序列
- 数据管道
掌握生成器函数,将帮助你编写更高效、更优雅的Python代码。生成器函数是Python中重要的概念,理解它的工作原理对于编写高效的Python程序至关重要。