本文目录导读:

Python 生成器(Generator)的典型用法主要体现在处理大数据流、惰性计算、无限序列和协程等场景,以下是几个经典的案例,从基础到进阶展示生成器的核心价值。
读取大文件(最经典)
避免一次性加载整个文件到内存。
def read_large_file(file_path):
"""逐行读取文件,每次只返回一行"""
with open(file_path, 'r', encoding='utf-8') as f:
for line in f:
yield line.strip()
# 使用示例:处理10GB的日志文件
for line in read_large_file('huge_log.txt'):
if 'ERROR' in line:
process_error(line) # 内存始终只占一行大小
斐波那契数列(无限序列)
生成器可以轻松表示无限序列,而不会耗尽内存。
def fibonacci():
"""生成无限的斐波那契数列"""
a, b = 0, 1
while True:
yield a
a, b = b, a + b
# 只取前10个
fib = fibonacci()
first_10 = [next(fib) for _ in range(10)]
print(first_10) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
# 或者用 itertools 切片
from itertools import islice
fib_slice = list(islice(fibonacci(), 5, 15)) # 第5到第14个
数据流式处理(管道模式)
将多个生成器串联起来形成处理管道。
def read_numbers(file_path):
"""从文件读取数字"""
with open(file_path) as f:
for line in f:
yield int(line.strip())
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(read_numbers('data.txt')))
for result in pipeline:
print(result) # 逐个处理,不生成中间列表
实现类似 range 的自定义序列
展示 yield 的控制流能力。
def my_range(start, stop=None, step=1):
"""模拟内置 range 函数,但更灵活"""
if stop is None:
start, stop = 0, start
if step == 0:
raise ValueError("step cannot be zero")
if step > 0:
while start < stop:
yield start
start += step
else:
while start > stop:
yield start
start += step
# 使用
for i in my_range(10, 0, -2):
print(i) # 10, 8, 6, 4, 2
协程与双向通信(yield 接收值)
展示了 yield 作为表达式接收外部值的用法。
def echo_processor():
"""处理并返回结果,同时接收外部输入"""
print("处理器启动...")
while True:
received = yield # 接收外部发送的值
print(f"收到: {received}")
# yield 也可以同时返回结果(需要先 send 启动)
# 这里用 yield 接收,不返回
# 使用
proc = echo_processor()
next(proc) # 启动到第一个 yield 处,输出 "处理器启动..."
proc.send("Hello") # 输出 "收到: Hello"
proc.send("World") # 输出 "收到: World"
# 更实用的例子:累加器
def accumulator():
total = 0
while True:
value = yield total # 返回当前总和,同时接收新值
total += value
acc = accumulator()
next(acc) # 启动
print(acc.send(10)) # 输出 10
print(acc.send(5)) # 输出 15
print(acc.send(3)) # 输出 18
生成器表达式(简洁写法)
与列表推导式类似,但返回生成器对象。
# 列表推导式:立即生成所有元素,占用内存
squares_list = [x**2 for x in range(1000000)] # 占用~8MB内存
# 生成器表达式:惰性计算,几乎不占内存
squares_gen = (x**2 for x in range(1000000)) # 生成器对象,内存很小
# 使用时才计算
for sq in squares_gen:
if sq > 100:
break
print(sq) # 只计算到第10个就停止了
# 实际应用:统计文件关键词
word_count = sum(1 for line in open('file.txt') if 'keyword' in line)
深度优先遍历(树结构)
生成器非常适合递归遍历树形结构。
class TreeNode:
def __init__(self, value, children=None):
self.value = value
self.children = children or []
def dfs(tree):
"""深度优先遍历生成器"""
yield tree.value
for child in tree.children:
yield from dfs(child) # yield from 简化递归生成
# 构建树
root = TreeNode(1, [
TreeNode(2, [TreeNode(4), TreeNode(5)]),
TreeNode(3, [TreeNode(6)])
])
# 遍历
print(list(dfs(root))) # [1, 2, 4, 5, 3, 6]
无限素数生成器
结合埃拉托色尼筛法,实现惰性素数序列。
def primes():
"""生成无限素数序列"""
yield 2
seen = {4: 2} # 合数: 最小质因子
n = 3
while True:
factor = seen.get(n)
if factor is None:
# n 是素数
yield n
seen[n * n] = n
else:
# n 是合数,更新下一个位置
next_val = n + factor
while next_val in seen:
next_val += factor
seen[next_val] = factor
del seen[n]
n += 2 # 只检查奇数
# 获取前20个素数
from itertools import islice
print(list(islice(primes(), 20)))
| 特性 | 列表/普通函数 | 生成器 |
|---|---|---|
| 内存占用 | 一次性加载所有 | 每次只处理一个元素 |
| 无限序列 | 不可能 | 天然支持 |
| 惰性计算 | 立即执行 | 按需计算 |
| 状态保存 | 需手动维护 | 自动保存执行状态 |
| 适用场景 | 数据量小、需要多次访问 | 大数据流、管道处理 |
选择生成器的黄金法则:如果你不需要同时访问所有元素,而只需要逐一处理,就应该考虑用生成器替换列表推导或普通函数。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播