1. 理解生成器的本质:一种特殊的迭代器
第一次接触Python生成器时,我误以为它只是另一种函数写法。直到在内存不足的场景下处理大型日志文件时,才真正体会到生成器的精妙之处。生成器本质上是一个能记住执行状态的函数,每次调用next()时从上次暂停的位置继续执行,而不是像普通函数那样每次从头开始。
与列表等容器对象不同,生成器采用惰性计算(Lazy Evaluation)策略。这意味着它不会一次性生成所有数据,而是按需产生值。这种特性在处理大规模数据流时尤其珍贵——我曾用生成器处理过超过20GB的CSV文件,而内存占用始终保持在MB级别。
python复制def simple_generator():
print("开始执行")
yield 1
print("继续执行")
yield 2
print("执行结束")
gen = simple_generator()
print(next(gen)) # 输出:开始执行 \n 1
print(next(gen)) # 输出:继续执行 \n 2
print(next(gen)) # 抛出StopIteration异常
关键理解:yield关键字会暂停函数执行并返回值,下次调用next()时从yield语句之后继续执行。这种"暂停-继续"机制是生成器的核心特征。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. yield关键字的运行机制
yield的行为看似简单,实则暗藏玄机。当函数执行到yield语句时,会发生三个关键操作:
- 返回yield右侧的表达式的值
- 保存当前函数的全部局部变量和执行状态
- 暂停执行,等待下一次next()调用
这种机制使得生成器能记住"执行上下文",包括局部变量、指令指针等。我曾用dis模块反编译过生成器函数的字节码,发现Python专门为yield实现了YIELD_VALUE等操作码来支持这种特殊流程控制。
python复制import dis
def count_down(n):
while n > 0:
yield n
n -= 1
dis.dis(count_down)
"""
3 0 SETUP_LOOP 26 (to 28)
