Python中的协程与生成器的区别与联系
字数 891 2025-11-09 09:09:11
Python中的协程与生成器的区别与联系
描述
协程和生成器都是Python中实现异步编程和惰性计算的重要机制,它们都使用了yield关键字,但在设计目的、功能和应用场景上有显著差异。生成器主要用于生成序列数据,而协程则专注于控制流的挂起与恢复,实现协作式多任务。理解二者的区别与联系,有助于在异步编程中选择合适的工具。
解题过程
-
生成器的核心功能
- 生成器是通过函数中包含
yield语句创建的迭代器,每次执行到yield时暂停,返回一个值,下次调用next()时从暂停处继续执行。 - 示例:
def simple_generator(): yield 1 yield 2 gen = simple_generator() print(next(gen)) # 输出1 print(next(gen)) # 输出2 - 生成器本质是数据生产者,专注于惰性生成序列,节省内存。
- 生成器是通过函数中包含
-
协程的扩展功能
- 协程通过
yield关键字实现双向通信,不仅能返回数据,还能接收外部调用者发送的数据。 - 使用
.send(value)方法向协程发送数据,yield表达式会接收发送的值。 - 示例:
def simple_coroutine(): print("启动协程") x = yield # 暂停并等待接收数据 print(f"接收到数据: {x}") coro = simple_coroutine() next(coro) # 启动协程,执行到第一个yield coro.send(42) # 发送数据,协程恢复执行 - 协程是数据消费者,核心在于挂起与调度,常用于异步IO或状态机。
- 协程通过
-
关键区别
- 设计目的:生成器用于生成迭代序列;协程用于控制流程的协作式切换。
- 数据流向:生成器通过
yield向外输出数据;协程通过yield同时支持输入和输出。 - 初始化和控制:生成器需用
next()启动;协程需先用next()或.send(None)启动至第一个yield。 - 演进:Python 3.5引入
async/await语法后,原生协程(如async def)不再依赖yield,与生成器彻底分离。
-
联系与演进
- 早期协程通过生成器实现(如
@asyncio.coroutine装饰器),共享yield机制。 - 生成器可视为协程的特例(仅输出数据),但协程更强调任务调度与状态保持。
- 现代区分:
- 生成器函数:包含
yield的函数,返回生成器对象。 - 原生协程:使用
async def定义,通过await挂起,不与生成器混用。
- 生成器函数:包含
- 早期协程通过生成器实现(如
-
总结
- 生成器是单行道(生产数据),协程是双行道(交互控制)。
- 在异步编程中,优先使用
async/await协程;生成器适用于简单惰性计算场景。