什么是Python生成器?
Python生成器(Generator)是一种特殊的迭代器,它允许你按需生成值,而不是一次性生成所有值并存储在内存中。生成器使用yield
关键字返回值,并在每次调用时从上次离开的位置继续执行。
关键特性: 生成器是惰性求值的,只在需要时生成数据,这使得它们非常适合处理大数据流或无限序列。
生成器函数 vs 普通函数
特性 | 普通函数 | 生成器函数 |
---|---|---|
返回值 | 使用return返回单一值 | 使用yield返回多个值 |
执行状态 | 每次调用从头开始执行 | 从上次yield的位置继续执行 |
内存使用 | 一次性返回所有结果 | 按需生成值,节省内存 |
使用场景 | 确定大小的数据集合 | 大数据流、无限序列 |
创建生成器的两种方式
1. 生成器函数
在函数中使用yield
关键字代替return
:
# 生成器函数示例
def countdown(n):
print("开始倒计时!")
while n > 0:
yield n # 每次调用next()时在这里暂停并返回n
n -= 1
# 创建生成器对象
cd = countdown(5)
# 使用生成器
print(next(cd)) # 输出: 5
print(next(cd)) # 输出: 4
print(next(cd)) # 输出: 3
生成器执行流程可视化
yield 5
yield 4
yield 3
yield 2
生成器在每次yield时暂停执行,保存当前状态,直到下一次调用next()
2. 生成器表达式
类似于列表推导式,但使用圆括号:
# 生成器表达式示例
squares = (x*x for x in range(1, 6))
# 使用生成器
print(next(squares)) # 输出: 1
print(next(squares)) # 输出: 4
print(next(squares)) # 输出: 9
# 或者使用for循环
for num in squares:
print(num) # 输出: 16, 25
注意: 生成器是单向的,只能遍历一次。遍历结束后,再次调用next()会引发StopIteration异常。
生成器的高级用法
send()方法向生成器发送数据
def accumulator():
total = 0
while True:
value = yield total # 接收发送的值
if value is None:
break
total += value
acc = accumulator()
next(acc) # 启动生成器,停在yield处
print(acc.send(10)) # 输出: 10
print(acc.send(20)) # 输出: 30
print(acc.send(5)) # 输出: 35
yield from 委派子生成器
def sub_generator():
yield 'Python'
yield 'Generator'
def main_generator():
yield '开始'
yield from sub_generator() # 委派给子生成器
yield '结束'
for item in main_generator():
print(item)
# 输出: 开始, Python, Generator, 结束
生成器的实际应用场景
1. 处理大型文件
逐行读取文件而不加载整个文件到内存:
def read_large_file(file_path):
with open(file_path, 'r', encoding='utf-8') as file:
for line in file:
yield line
# 使用示例
for line in read_large_file('huge_data.txt'):
process_line(line) # 处理每一行
2. 生成无限序列
创建无限序列而不占用无限内存:
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
fib = fibonacci()
for _ in range(10):
print(next(fib)) # 打印前10个斐波那契数
3. 数据管道处理
将多个生成器连接成数据处理管道:
def read_data(file):
for line in file:
yield line.strip()
def filter_comments(lines):
for line in lines:
if not line.startswith('#'):
yield line
def to_upper(lines):
for line in lines:
yield line.upper()
# 构建处理管道
pipeline = to_upper(filter_comments(read_data(open('data.txt')))
for processed_line in pipeline:
print(processed_line)
总结
Python生成器是处理大数据集、创建数据管道和实现高效迭代的强大工具。通过使用yield
关键字,生成器可以:
- 按需生成值,节省内存
- 保持函数的执行状态
- 创建复杂的数据处理管道
- 实现无限序列
- 简化异步编程(协程的基础)
掌握生成器将大幅提升你的Python编程能力,特别是在数据处理和内存优化方面。
发表评论