Python 2.2 引入了 yield 关键字实现的生成器函数,大约五年后,Python 2.5 实现了“PEP 342 — Coroutines via Enhanced Generators”(https://www.python.org/dev/peps/pep-0342/)。这个提案为生成器对象添加了额外的方法和功能,其中最值得关注的是 .send() 方法。

.__next__() 方法一样,.send() 方法致使生成器前进到下一个 yield 语句。不过,.send() 方法还允许使用生成器的客户把数据发给自己,即不管传给 .send() 方法什么参数,那个参数都会成为生成器函数定义体中对应的 yield 表达式的值。也就是说,.send() 方法允许在客户代码和生成器之间双向交换数据。而 .__next__() 方法只允许客户从生成器中获取数据。

这是一项重要的“改进”,甚至改变了生成器的本性:像这样使用的话,生成器就变身为协程。在 PyCon US 2009 期间举办的一场著名的课程中(http://www.dabeaz.com/coroutines/),David Beazley(可能是 Python 社区中在协程方面最多产的作者和演讲者)提醒道:

——David Beazley
“A Curious Course on Coroutines and Concurrency”

16摘自“A Curious Course on Coroutines and Concurrency”(http://www.dabeaz.com/coroutines/Coroutines.pdf)的第 33 张幻灯片,题为“Keeping It Straight”。

我会遵从他的建议,至此结束本章(因为本章真正讨论的是迭代技术),而不涉及把生成器当成协程使用的 send 方法和其他特性。第 16 章会讨论协程。