yield from
yield from x 表达式对 x 对象所做的第一件事是,调用 iter(x),从中获取迭代器。因
此, x 可以是任何可迭代的对象。
可是,如果 yield from 结构唯一的作用是替代产出值的嵌套 for 循环,这个结构很有
可能不会添加到 Python 语言中。 yield from 结构的本质作用无法通过简单的可迭代对象
说明,而要发散思维,使用嵌套的生成器。因此,引入 yield from 结构的 PEP 380 才起
了“Syntax for Delegating to a Subgenerator”(“把职责委托给子生成器的句法”)这个标题。
yield from 的主要功能是打开双向通道,把最外层的调用方与最内层的子生成器连接起
来,这样二者可以直接发送和产出值,还可以直接传入异常,而不用在位于中间的协程中
添加大量处理异常的样板代码。有了这个结构,协程可以通过以前不可能的方式委托职责。
若想使用 yield from 结构,就要大幅改动代码。为了说明需要改动的部分, PEP 380 使
用了一些专门的术语。 委派生成器
  包含 yield from <iterable> 表达式的生成器函数。 子生成器
  从 yield from 表达式中 <iterable> 部分获取的生成器。这就是 PEP 380 的标题
(“Syntax for Delegating to a Subgenerator”)中所说的“子生成器”(subgenerator)。 调用方
PEP 380 使用“调用方”这个术语指代调用委派生成器的客户端代码。 子生成器可能是简单的迭代器,只实现了 __next__ 方法;但是, yield from 也能处理这种子生成器。
不过,引入 yield from 结构的目的是为了支持实现了 __next__、 send、 close 和throw 方法的生成器。 如果子生成器不终止,委派生成器会在 yield from 表达式处永远暂停。如果是这样,程序不会向前执行,
因为 yield from(与 yield 一样)把控制权转交给客户代码(即,委派生成器的调用方)了。显然,
肯定有任务无法完成. 因为委派生成器相当于管道,所以可以把任意数量个委派生成器连接在一起:一个委派生成器使用
yield from 调用一个子生成器,而那个子生成器本身也是委派生成器,使用 yield from
调用另一个子生成器,以此类推。最终,这个链条要以一个只使用 yield 表达式的简单生成器结束;
不过,也能以任何可迭代的对象结束. 任何 yield from 链条都必须由客户驱动,在最外层委派生成器上调用 next(...) 函数
或 .send(...) 方法。可以隐式调用,例如使用 for 循环。 批准后的 PEP 380 在“Proposal”一节(https://www.python.org/dev/peps/pep-0380/#proposal)
分六点说明了 yield from 的行为。
a, 子生成器产出的值都直接传给委派生成器的调用方(即客户端代码)。
b, 使用 send() 方法发给委派生成器的值都直接传给子生成器。如果发送的值是
None,那么会调用子生成器的 __next__() 方法。如果发送的值不是 None,那么会
调用子生成器的 send() 方法。如果调用的方法抛出 StopIteration 异常,那么委
派生成器恢复运行。任何其他异常都会向上冒泡,传给委派生成器。
c, 生成器退出时,生成器(或子生成器)中的 return expr 表达式会触发
StopIteration(expr) 异常抛出。
d, yield from 表达式的值是子生成器终止时传给 StopIteration 异常的第一个参数。
e, yield from 结构的另外两个特性与异常和终止有关。传入委派生成器的异常,
除了 GeneratorExit 之外都传给子生成器的 throw() 方法。如果调用 throw()
方法时抛出 StopIteration 异常,委派生成器恢复运行。 StopIteration 之外的
异常会向上冒泡,传给委派生成器。
f, 如果把 GeneratorExit 异常传入委派生成器,或者在委派生成器上调用 close() 方
法,那么在子生成器上调用 close() 方法,如果它有的话。如果调用 close() 方法
导致异常抛出,那么异常会向上冒泡,传给委派生成器;否则,委派生成器抛出 GeneratorExit 异常。

coroutine - yield from的更多相关文章

  1. ngx_lua_API 指令详解(五)coroutine.create,coroutine.resume,coroutine.yield 等集合指令介绍

    ngx_lua 模块(原理实现) 1.每个worker(工作进程)创建一个Lua VM,worker内所有协程共享VM: 2.将Nginx I/O原语封装后注入 Lua VM,允许Lua代码直接访问: ...

  2. Python协程:从yield/send到async/await

    这个文章理好了脉落. http://python.jobbole.com/86069/ 我练 习了一番,感受好了很多... Python由于众所周知的GIL的原因,导致其线程无法发挥多核的并行计算能力 ...

  3. lua coroutine for iterator

    背景 前面的文章演示了使用闭包函数实现 状态的迭代器. 本文演示使用 coroutine来产生迭代器的例子. coroutine迭代器例子 -- 遍历二叉树 local binary_tree = { ...

  4. Lua Coroutine详解

    协同程序与线程差不多,也就是一条执行序列,拥有自己独立的栈,局部变量和指令指针,同时又与其它协同程序共享全局变量和其它大部分东西.线程与协同程序的主要区别在于,一个具有多线程的程序可以同时运行几个线程 ...

  5. Lua 协程coroutine

    协程和一般多线程的区别是,一般多线程由系统决定该哪个线程执行,是抢占式的,而协程是由每个线程自己决定自己什么时候不执行,并把执行权主动交给下一个线程. 协程是用户空间线程,操作系统其存在一无所知,所以 ...

  6. 【转】Lua coroutine 不一样的多线程编程思路

    Lua coroutine 不一样的多线程编程思路 Sunday, Apr 26th, 2009 by Tim | Tags: coroutine, Lua 上周末开始看<Lua程序设计> ...

  7. Lua中的协同程序 coroutine

    Lua中的协程和多线程很相似,每一个协程有自己的堆栈,自己的局部变量,可以通过yield-resume实现在协程间的切换.不同之处是:Lua协程是非抢占式的多线程,必须手动在不同的协程间切换,且同一时 ...

  8. JSBinding + SharpKit / Coroutine支持

    首先得深入了解协程的原理.如果还没有完全理解,建议看这篇: http://wiki.unity3d.com/index.php/CoroutineScheduler 另外还要对 JavaScript ...

  9. (zt)Lua的多任务机制——协程(coroutine)

    原帖:http://blog.csdn.net/soloist/article/details/329381 并发是现实世界的本质特征,而聪明的计算机科学家用来模拟并发的技术手段便是多任务机制.大致上 ...

随机推荐

  1. C++生成dll以及调用(函数)和类

    C++新手,方法可能有很多,此方法仅仅是自己实验并可行,详细步骤如下: 生成dll文件和lib文件: (1) 新建项目-windows桌面向导,选择动态链接.dll以及空项目: (2)复制代码(头文件 ...

  2. 最新IDEA永久激活攻略

    前言 写这篇文章的原因是我最近想自己写两个项目,却发现自己的IDEA过期了,对,就是那个JAVA编辑器,于是研究了一下IDEA的激活.发现网上的攻略大多数不可用. 当然这里推荐大家去官网购买正版使用. ...

  3. 主席树 - 查询某区间第 K 大

    You are working for Macrohard company in data structures department. After failing your previous tas ...

  4. 关于在读取excel的文件时候,放在服务器上就报路径错误

    就是指定这个路径:C:\Program Files (x86)\IIS Express 因为在上传到服务器的时候,服务器读取的是在服务器上的路径,所以正确的思路应该是 把上传的Excel存在服务器上, ...

  5. java 魔术

    每4个字节都有对应的含义

  6. Vue 组件复用性和slot

    1.组件可复用 2.slot元素作为组件模板之中的内容分发插槽,元素自身可以被替换 <!DOCTYPE html> <html lang="en"> < ...

  7. Application run failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name

    目前有发现的两种情况 第一种:是在继承jpa的时候检查实体类@id和@Entity引进的包是否是 import javax.persistence.Id imprt javax.persistence ...

  8. 04--Java--使用eclipse创建开发java项目步骤

    eclipse创建开发java步骤 1.三种创建java项目 1)方式一:在包资源管理器(package explorer)窗口中鼠标右击任意位置选择New --> Java Project,如 ...

  9. ios--->上下拉刷新控件MJRefresh

    上下拉刷新控件MJRefresh 一.类结构 MJRefreshComponent.h MJRefreshHeader.h MJRefreshFooter.h MJRefreshAutoFooter. ...

  10. Linux 安装tomcat及tomcat自带远程部署项目与管理

    准备: 1.Linux系统 2.已经安装好jdk 开始: 选择要安装的tomcat版本:https://archive.apache.org/dist/tomcat/ 我这里使用的是tomcat 8. ...