coroutine - yield from
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的更多相关文章
- ngx_lua_API 指令详解(五)coroutine.create,coroutine.resume,coroutine.yield 等集合指令介绍
ngx_lua 模块(原理实现) 1.每个worker(工作进程)创建一个Lua VM,worker内所有协程共享VM: 2.将Nginx I/O原语封装后注入 Lua VM,允许Lua代码直接访问: ...
- Python协程:从yield/send到async/await
这个文章理好了脉落. http://python.jobbole.com/86069/ 我练 习了一番,感受好了很多... Python由于众所周知的GIL的原因,导致其线程无法发挥多核的并行计算能力 ...
- lua coroutine for iterator
背景 前面的文章演示了使用闭包函数实现 状态的迭代器. 本文演示使用 coroutine来产生迭代器的例子. coroutine迭代器例子 -- 遍历二叉树 local binary_tree = { ...
- Lua Coroutine详解
协同程序与线程差不多,也就是一条执行序列,拥有自己独立的栈,局部变量和指令指针,同时又与其它协同程序共享全局变量和其它大部分东西.线程与协同程序的主要区别在于,一个具有多线程的程序可以同时运行几个线程 ...
- Lua 协程coroutine
协程和一般多线程的区别是,一般多线程由系统决定该哪个线程执行,是抢占式的,而协程是由每个线程自己决定自己什么时候不执行,并把执行权主动交给下一个线程. 协程是用户空间线程,操作系统其存在一无所知,所以 ...
- 【转】Lua coroutine 不一样的多线程编程思路
Lua coroutine 不一样的多线程编程思路 Sunday, Apr 26th, 2009 by Tim | Tags: coroutine, Lua 上周末开始看<Lua程序设计> ...
- Lua中的协同程序 coroutine
Lua中的协程和多线程很相似,每一个协程有自己的堆栈,自己的局部变量,可以通过yield-resume实现在协程间的切换.不同之处是:Lua协程是非抢占式的多线程,必须手动在不同的协程间切换,且同一时 ...
- JSBinding + SharpKit / Coroutine支持
首先得深入了解协程的原理.如果还没有完全理解,建议看这篇: http://wiki.unity3d.com/index.php/CoroutineScheduler 另外还要对 JavaScript ...
- (zt)Lua的多任务机制——协程(coroutine)
原帖:http://blog.csdn.net/soloist/article/details/329381 并发是现实世界的本质特征,而聪明的计算机科学家用来模拟并发的技术手段便是多任务机制.大致上 ...
随机推荐
- git利用hooks实现自动部署
准备工作: 1.一台虚拟linux环境和window 开始工作 1.安装git(略) 2.创建git用户和创建test.git裸仓库 [root@localhost ~]# useradd -m gi ...
- C++Primer第五版 6.1节练习
练习6.1:实参和形参的区别是什么? 通俗解释: 实参是形参的初始值.编译器能以任意可行的顺序对实参求值.实参的类型必须与对应的形参类型匹配. 详解1) 形参变量只有在函数被调用时才会分配内存,调用结 ...
- 曹工说Spring Boot源码(11)-- context:component-scan,你真的会用吗(这次来说说它的奇技淫巧)
写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...
- Java入门 - 面向对象 - 06.接口
原文地址:http://www.work100.net/training/java-interface.html 更多教程:光束云 - 免费课程 接口 序号 文内章节 视频 1 概述 2 接口的声明 ...
- 【Java并发基础】使用“等待—通知”机制优化死锁中占用且等待解决方案
前言 在前篇介绍死锁的文章中,我们破坏等待占用且等待条件时,用了一个死循环来获取两个账本对象. // 一次性申请转出账户和转入账户,直到成功 while(!actr.apply(this, targe ...
- Quartz cron 表达式(linux 定时器,java 定时任务,spring task定时任务)
原文地址:https://blog.csdn.net/feng27156/article/details/39293403 Quartz cron 表达式的格式十分类似于 UNIX cron 格式,但 ...
- C语言实现按位拷贝
在程序开发过程中,我们经常会用到按位拷贝一串二进制数,在此提供一个按位拷贝的函数给大家参考,函数源码如下: #define char_t char #define uint8_t unsigned c ...
- 创建dynamics CRM client-side (十四) - Web API
Xrm.WebApi 是我们做前端开发不可不缺少的内容. Xrm.WebApi 分为online和offline online: 可以实现和服务器的CRUD交互 offline: 多用于mobile ...
- Commvault逻辑架构及组件说明
在学习和使用Commvault软件的过程中,经常会碰到一些术语和缩写,初学者可能并不是很清楚这些术语和缩写的具体含义,接下来我们梳理一下Commvault软件中这些属于和缩写的含义,有可能一次不能梳理 ...
- linux下误清用户/home下的文件怎么办?
2016-08-19 10:38:10 有时候我们不小心把home目录下的用户目录删除了,出现上图情况,每行开头直接变成-bash-3.2$这种形式而不是[lyp@centos7 ~]$这种,这时 ...