python协程的实现经历了三个阶段:生成器、基于生成器的协程和async/await。最初,生成器通过yield和.send()实现了基本的协程功能,具备暂停、恢复及双向通信能力;随后,@asyncio.coroutine装饰器配合yield from实现了异步任务调度,但仍存在语法不直观、需手动管理事件循环等问题;最终,python 3.5引入async/await语法,async def定义协程函数,await替代yield from,语义更清晰,协程标识更明确,同时event loop也逐步简化并模块化,提升了异步编程效率与性能。
在 Python 中,协程(coroutine)的实现并不是一蹴而就的,而是随着语言的发展逐步演进而来。从最初的生成器(generator)到如今我们熟悉的 async/await 语法,整个过程可以说是 Python 异步编程的一段进化史。
Python 的协程最早是基于生成器构建的。生成器由 yield 关键字引入,在早期版本中主要用于惰性地生成数据流。
但人们很快发现,yield 不仅可以用来“产出”值,还可以通过 .send() 方法接收外部传入的值,这使得生成器具备了“双向通信”的能力。于是,生成器变成了可以暂停、恢复执行的函数,这就是协程的雏形。
举个简单的例子:
立即学习“Python免费学习笔记(深入)”;
def simple_coroutine(): x = yield print("Received:", x) coro = simple_coroutine() next(coro) # 启动协程 coro.send(42) # 输出 Received: 42
这个例子展示了协程的基本行为:暂停和恢复,并且能接收外部输入。虽然看起来简单,但正是这种机制为后来的异步编程打下了基础。
当开发者开始用生成器模拟协程时,出现了像 @asyncio.coroutine 这样的装饰器,它本质上就是把一个生成器标记为协程。
这时候的协程需要手动调度,比如使用 yield from 来嵌套调用其他协程:
@asyncio.coroutine def sub_coroutine(): print("Start sub") yield from asyncio.sleep(1) print("End sub") @asyncio.coroutine def main(): yield from sub_coroutine() asyncio.get_event_loop().run_until_complete(main())
这种方式虽然可行,但有几个问题:
为了改进这些问题,Python 3.5 引入了 async/await 语法,标志着现代协程的正式登场。
上面的例子改写成 async/await 版本如下:
async def sub_coroutine(): print("Start sub") await asyncio.sleep(1) print("End sub") async def main(): await sub_coroutine() asyncio.run(main())
这样写的好处很明显:
在 async/await 初期,还需要手动获取和运行 event loop,比如:
loop = asyncio.get_event_loop() loop.run_until_complete(main())
但从 Python 3.7 开始,可以直接使用 asyncio.run(main()),内部自动创建并关闭 event loop,简化了使用流程。
另外,event loop 的实现也逐渐模块化,允许第三方库自定义(如 uvloop),这也让 Python 的异步性能有了很大提升空间。
基本上就这些内容了。理解这段历史,不仅能帮助你更好地写出高质量的异步代码,也能让你明白为什么现在推荐用 async/await 而不是老式的生成器方式。
以上就是Python里协程实现原理 从生成器到async/await的协程发展史的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号