协程的底层架构在“PEP 342—Coroutines via Enhanced Generators”(https://www.python.org/dev/peps/pep-0342/)中定义,并在 Python 2.5(2006 年)实现了。自此之后,yield 关键字可以在表达式中使用,而且生成器 API 中增加了 .send(value) 方法。生成器的调用方可以使用 .send(...) 方法发送数据,发送的数据会成为生成器函数中 yield 表达式的值。因此,生成器可以作为协程使用。协程是指一个过程,这个过程与调用方协作,产出由调用方提供的值。
除了 .send(...) 方法,PEP 342 还添加了 .throw(...) 和 .close() 方法:前者的作用是让调用方抛出异常,在生成器中处理;后者的作用是终止生成器。下一节和 16.5 节会说明这些方法。
协程最近的演进来自 Python 3.3(2012 年)实现的“PEP 380—Syntax for Delegating to a Subgenerator”(https://www.python.org/dev/peps/pep-0380/)。PEP 380 对生成器函数的句法做了两处改动,以便更好地作为协程使用。
现在,生成器可以返回一个值;以前,如果在生成器中给 return 语句提供值,会抛出 SyntaxError 异常。
新引入了 yield from 句法,使用它可以把复杂的生成器重构成小型的嵌套生成器,省去了之前把生成器的工作委托给子生成器所需的大量样板代码。
这两个最新的改动分别在 16.6 节和 16.7 节讨论。
按照本书的惯例,我们先从基本概念和示例入手,然后再深入越来越难以理解的特性。