coroutine - yield from

 1 yield from
 2     yield from x 表达式对 x 对象所作的第一件事是,调用 iter(x),从中获取迭代器。因
 3     此, x 能够是任何可迭代的对象。
 4     但是,若是 yield from 结构惟一的做用是替代产出值的嵌套 for 循环,这个结构颇有
 5     可能不会添加到 Python 语言中。 yield from 结构的本质做用没法经过简单的可迭代对象
 6     说明,而要发散思惟,使用嵌套的生成器。所以,引入 yield from 结构的 PEP 380 才起
 7     了“Syntax for Delegating to a Subgenerator”(“把职责委托给子生成器的句法”)这个标题。
 8     yield from 的主要功能是打开双向通道,把最外层的调用方与最内层的子生成器链接起
 9     来,这样两者能够直接发送和产出值,还能够直接传入异常,而不用在位于中间的协程中
10     添加大量处理异常的样板代码。有了这个结构,协程能够经过之前不可能的方式委托职责。
11     若想使用 yield from 结构,就要大幅改动代码。为了说明须要改动的部分, PEP 380 使
12     用了一些专门的术语。
13     
14     委派生成器
15       包含 yield from <iterable> 表达式的生成器函数。
16     
17     子生成器
18       从 yield from 表达式中 <iterable> 部分获取的生成器。这就是 PEP 380 的标题
19        (“Syntax for Delegating to a Subgenerator”)中所说的“子生成器”(subgenerator)。
20    
21     调用方
22         PEP 380 使用“调用方”这个术语指代调用委派生成器的客户端代码。
23     
24     子生成器多是简单的迭代器,只实现了 __next__ 方法;可是, yield from 也能处理这种子生成器。
25     不过,引入 yield from 结构的目的是为了支持实现了 __next__、 send、 close 和throw 方法的生成器。
26     
27     若是子生成器不终止,委派生成器会在 yield from 表达式处永远暂停。若是是这样,程序不会向前执行,
28     由于 yield from(与 yield 同样)把控制权转交给客户代码(即,委派生成器的调用方)了。显然,
29     确定有任务没法完成.
30     
31     由于委派生成器至关于管道,因此能够把任意数量个委派生成器链接在一块儿:一个委派生成器使用 
32     yield from 调用一个子生成器,而那个子生成器自己也是委派生成器,使用 yield from 
33     调用另外一个子生成器,以此类推。最终,这个链条要以一个只使用 yield 表达式的简单生成器结束;
34     不过,也能以任何可迭代的对象结束.
35     
36     任何 yield from 链条都必须由客户驱动,在最外层委派生成器上调用 next(...) 函数
37     或 .send(...) 方法。能够隐式调用,例如使用 for 循环。
38     
39 批准后的 PEP 380 在“Proposal”一节(https://www.python.org/dev/peps/pep-0380/#proposal)
40 分六点说明了 yield from 的行为。
41     a, 子生成器产出的值都直接传给委派生成器的调用方(即客户端代码)。
42     b, 使用 send() 方法发给委派生成器的值都直接传给子生成器。若是发送的值是
43        None,那么会调用子生成器的 __next__() 方法。若是发送的值不是 None,那么会
44        调用子生成器的 send() 方法。若是调用的方法抛出 StopIteration 异常,那么委
45        派生成器恢复运行。任何其余异常都会向上冒泡,传给委派生成器。
46     c, 生成器退出时,生成器(或子生成器)中的 return expr 表达式会触发
47        StopIteration(expr) 异常抛出。
48     d, yield from 表达式的值是子生成器终止时传给 StopIteration 异常的第一个参数。
49     e, yield from 结构的另外两个特性与异常和终止有关。传入委派生成器的异常,
50        除了 GeneratorExit 以外都传给子生成器的 throw() 方法。若是调用 throw() 
51        方法时抛出 StopIteration 异常,委派生成器恢复运行。 StopIteration 以外的
52        异常会向上冒泡,传给委派生成器。     
53     f, 若是把 GeneratorExit 异常传入委派生成器,或者在委派生成器上调用 close() 方
54        法,那么在子生成器上调用 close() 方法,若是它有的话。若是调用 close() 方法
55        致使异常抛出,那么异常会向上冒泡,传给委派生成器;不然,委派生成器抛出 GeneratorExit 异常。 
相关文章
相关标签/搜索