什么是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编程能力,特别是在数据处理和内存优化方面。