Python中的生成器和yield详细介绍

大哥大姐打扰一下,Python中的生成器和yield详细介绍
最新回答
汐水溪西惝

2026-10-22 09:31:40

Python中的生成器(Generator)和yield关键字是用于高效处理大规模数据或实现惰性求值的重要工具。 生成器通过yield关键字逐个产生值,而非一次性生成所有数据,从而节省内存并支持协程等高级功能。以下是详细解析:

1. 生成器表达式 vs 列表推导
  • 列表推导:直接生成完整列表并存储在内存中,适合小规模数据。squares = [n*n for n in range(3)] # 输出 [0, 1, 4]
  • 生成器表达式:使用小括号,惰性生成值,节省内存。squares = (n*n for n in range(3)) # 输出生成器对象,迭代时逐个计算
2. 生成器函数
  • 定义:包含yield关键字的函数,返回一个生成器对象。
  • 执行机制:

    调用生成器函数时,函数体不立即执行,而是返回生成器对象。

    每次调用next()或迭代时,执行到yield暂停并返回值,下次从暂停处继续。

    def countdown(n): while n > 0: yield n # 暂停并返回n n -= 1gen = countdown(3)print(next(gen)) # 输出 3print(next(gen)) # 输出 2
3. yield的核心功能
  • 惰性求值:仅在需要时生成值,避免内存爆炸。
  • 状态保存:函数局部变量和执行位置在yield后保留,下次恢复。
  • 终止信号:生成器结束时抛出StopIteration异常。
4. 协程(Coroutine)与双向通信
  • 协程:生成器通过yield实现接收和发送数据的双向通信。

    启动协程:首次调用next()或send(None)执行到第一个yield。

    发送数据:send(value)将值赋给yield左侧变量,并继续执行。

    def recv(): print('Ready') while True: n = yield # 接收外部数据 print('Got:', n)coro = recv()coro.send(None) # 启动协程coro.send(10) # 输出 "Got: 10"
  • 返回值:yield右侧表达式的结果通过send()返回。
5. 生成器的应用场景
  • 处理大规模数据:如逐行读取文件,避免内存不足。def read_large_file(file_path): with open(file_path) as f: for line in f: yield line.strip()
  • 实现管道处理:多个协程串联处理数据流(如文件查找→打开→读取→打印)。@default_nextdef find_files(target): topdir = yield for root, _, files in os.walk(topdir): for file in files: target.send(os.path.join(root, file))
6. 生成器与迭代器的关系
  • 生成器是特殊的迭代器,自动实现__iter__()和__next__()方法。
  • 可通过next()逐个获取值,或直接用于for循环。
7. 注意事项
  • 协程启动:首次必须用next()或send(None)激活。
  • 资源释放:显式调用close()终止生成器,避免资源泄漏。
  • 异常处理:生成器内可捕获外部传入的异常(如StopIteration)。
总结

生成器通过yield实现惰性求值和协程通信,显著提升内存效率和程序灵活性。掌握生成器表达式、函数及协程用法,能高效处理流式数据、构建复杂管道,甚至实现轻量级并发。