深度解析python生成器和关键字yield

一、生成器概述

生成器(Generator)是Python中用于创建迭代器的工具,通过yield关键字实现。与普通函数不同,生成器函数返回的是迭代器对象,具有以下核心特性:

  1. 内存效率:只在需要时生成值,适合处理大数据流

  2. 状态保持:自动保存执行上下文

  3. 惰性计算:按需生成元素,节省计算资源

# 普通函数 vs 生成器函数
def normal_func():
    return [x for x in range(1000000)]  # 立即创建百万元素列表
def generator_func():
    for x in range(1000000):
        yield x  # 每次只生成一个元素

二、生成器基础用法

1. 创建生成器

def simple_generator():
    print("启动生成器")
    yield 1
    yield 2
    yield 3
gen = simple_generator()  # 创建生成器对象
print(type(gen))  # <class 'generator'>

2. 使用生成器

# 手动迭代
print(next(gen))  # 输出:启动生成器 1
print(next(gen))  # 2
print(next(gen))  # 3
# 自动迭代
for num in simple_generator():
    print(num)  # 依次输出1,2,3

三、执行流程解析

通过调试模式观察执行流程:

def countdown(n):
    print("开始倒计时")
    while n > 0:
        yield n
        n -= 1
    print("发射!")
cd = countdown(3)
print(next(cd))  # 输出:开始倒计时 3
print(next(cd))  # 2 
print(next(cd))  # 1
print(next(cd))  # 抛出StopIteration并打印"发射!"

执行流程图解:

首次next() → 执行到第一个yield暂停
↓
后续next() → 从上个yield之后继续执行到下一个yield
↓
循环直到函数结束,抛出StopIteration

四、高级应用技巧

1. 生成器表达式

squares = (x**2 for x in range(10))
print(sum(squares))  # 285

2. 双向通信

def interactive_gen():
    total = 0
    while True:
        value = yield total  # 接收外部传入值
        if value is None:
            break
        total += value
ig = interactive_gen()
next(ig)  # 启动生成器
print(ig.send(10))  # 10
print(ig.send(20))  # 30

3. 异常处理

def safe_gen():
    try:
        yield 1
        yield 2
    except ValueError:
        yield "错误处理"
        
sg = safe_gen()
print(next(sg))  # 1
sg.throw(ValueError)  # 输出:错误处理

4. 组合生成器

def chain_generators(*iterables):
    for it in iterables:
        yield from it  # Python 3.3+语法
for num in chain_generators(range(3), (5,6)):
    print(num)  # 输出0,1,2,5,6

五、典型应用场景

1. 大文件处理

def read_large_file(file_path):
    with open(file_path, 'r') as f:
        while True:
            chunk = f.read(4096)
            if not chunk:
                break
            yield chunk

2. 无限序列

def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b
fib = fibonacci()
print([next(fib) for _ in range(10)])  # [0,1,1,2,3,5,8,13,21,34]

3. 状态机实现

def traffic_light():
    states = ['RED', 'GREEN', 'YELLOW']
    index = 0
    while True:
        yield states[index]
        index = (index + 1) % 3
light = traffic_light()
print(next(light))  # RED
print(next(light))  # GREEN

六、注意事项

  1. 单次使用性
gen = (x for x in range(3))
print(list(gen))  # [0,1,2]
print(list(gen))  # []

  1. 上下文管理器
from contextlib import contextmanager
@contextmanager
def gen_context():
    print("进入上下文")
    try:
        yield "资源"
    finally:
        print("清理资源")
with gen_context() as res:
    print(f"正在使用 {res}")  # 进入上下文 → 正在使用资源 → 清理资源

  1. 性能对比(数据量=1,000,000):
列表推导式:内存占用  82MB,耗时 0.1s
生成器表达式:内存占用 <1MB,耗时 0.08s

七、总结与建议

核心优势

  • 内存友好型数据处理

  • 支持惰性求值

  • 简化迭代器实现

  • 实现协程基础

学习建议

  1. 从简单计数器开始练习

  2. 尝试改写现有列表处理代码为生成器版本

  3. 探索itertools模块的生成器工具

  4. 学习异步编程时结合async/await语法

进阶路线

生成器 → 迭代器协议 → 协程 → 异步IO

# 综合示例:分页查询生成器
def paginated_query(query):
    page = 1
    while True:
        results = get_results(query, page)
        if not results:
            break
        yield from results
        page += 1
# 使用示例
for record in paginated_query("SELECT * FROM big_table"):
    process(record)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凌叁儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值