哪些Python案例展示了生成器用法?

wen python案例 8

本文目录导读:

哪些Python案例展示了生成器用法?

  1. 读取大文件(最经典)
  2. 斐波那契数列(无限序列)
  3. 数据流式处理(管道模式)
  4. 实现类似 range 的自定义序列
  5. 协程与双向通信(yield 接收值)
  6. 生成器表达式(简洁写法)
  7. 深度优先遍历(树结构)
  8. 无限素数生成器

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)))
特性 列表/普通函数 生成器
内存占用 一次性加载所有 每次只处理一个元素
无限序列 不可能 天然支持
惰性计算 立即执行 按需计算
状态保存 需手动维护 自动保存执行状态
适用场景 数据量小、需要多次访问 大数据流、管道处理

选择生成器的黄金法则:如果你不需要同时访问所有元素,而只需要逐一处理,就应该考虑用生成器替换列表推导或普通函数。

抱歉,评论功能暂时关闭!