Python技术迷

解释协程(coroutine)与生成器(generator)的异同。

我刚开始学 Python 的时候,最容易搞混的两个概念就是协程和生成器。看文档上都写着“用 yield 实现的”,脑子里瞬间就乱成一锅粥。后来踩了几次坑,写过点 demo,才慢慢把它们区分开。

先聊生成器

生成器你可以理解成“会记住自己运行到哪的函数”。 比如一个普通函数,调用一次跑完就结束了,对吧?但如果函数里用了 yield,它就能一边跑一边暂停,下次再跑还能接着来。

defsimple_gen():
    print("step 1")
yield1
    print("step 2")
yield2

g = simple_gen()
print(next(g))  # 输出 step 1\n1
print(next(g))  # 输出 step 2\n2

运行的时候你会发现,它不会一次性把内容全跑完,而是每次 next() 往前推进一点点。这个特性特别适合处理大数据流,内存友好嘛。

再看协程

协程其实就是生成器的“进阶版”,但核心思想还是那个“可以暂停和恢复”的能力。区别在于:生成器主要是单向的产出数据,而协程是可以双向通信的。

举个例子:

defsimple_coro():
    print("协程开始")
    x = yield"ready"
    print("协程收到:", x)
yield x * 2

c = simple_coro()
print(next(c))          # 启动协程 -> 输出 "ready"
print(c.send(10))       # 传值进去 -> 输出 "协程收到: 10" 然后返回 20

这里的 send() 就是协程和外部交互的关键。生成器里一般是“产出”东西,而协程可以“产出 + 接收”,更灵活。

它俩的关系

  • 底层机制:协程最早就是基于生成器语法糖 (yield + send) 实现的,所以看起来很像。
  • 应用场景:生成器多用于“迭代、懒加载、大数据流”,协程则偏向“异步编程、事件循环”那一类。
  • 易用性:现在大家写协程更多用 async/await,这其实是 Python 给协程专门设计的新语法,看起来更直观:
import asyncio

asyncdeftask(name):
    print(f"{name} start")
await asyncio.sleep(1)
    print(f"{name} done")

asyncdefmain():
await asyncio.gather(task("A"), task("B"))

asyncio.run(main())

这段代码在事件循环里跑,相当于同时执行了两个任务。用生成器能做到类似的效果,但写起来就没这么舒服了。

所以啊,生成器更像是“会记忆的迭代器”,协程则是“能对话的生成器”。Python 一开始是用生成器语法来玩协程的,但随着异步需求越来越多,就干脆整了一套 async/await 体系出来。

如果你只是要处理文件、数据流,生成器就够了;要是写网络 IO、多任务调度,那协程才是正解。

-END-

我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html

🔥虎哥私藏精品🔥

虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB,点击下方公众号回复关键字 python 全部免费领