关于yield详细可参考我这篇文章
下面是一个带yield的生成器:
def gen_yield():
while True:
recv = yield
do something with recv
现在我们不单独使用gen_yield这生成器,而是通过另一个携程outer_yield完成必要的验证、设置等再去使用它
def outer_yield():
chiled_gen = gen_yield()
chiled_gen.send(None) #准备上子携程
do something just like setting or you want #在这儿做一些设置或者验证工作
while True:
recv = yield
chiled_gen.send(recv) #把上面接收到的消息,发送到子携程处理
以上可知,yield 只允许协程与外界直接交互而不能使得子协程与外界直接交互。而且,我们这里还没有考虑子协程抛出异常,返回等情况。
yield form 应运而生来解决这个问题:
def gen_yield():
while True:
recv = yield
do something with recv
def new_outer():
do something you want
yield from gen_yield() #1 yield from 后必须跟generator object
no = new_outer()
no.send(None) #2启动生成器
这儿我们可以理解为#1 处yield from 把工作下发(委托)给了gen_yield()子生成器
而当#2出外界开始send值与outer交互时,outer直接通过yield from把值发送给子生成器gen_yield执行
这样就达到了外界直接与子生成器直接交互的功能。
总结:
- 所有new_outer的实例作为调用者把值send过去,都等于直接发送给了子迭代器gen_yield,而子迭代器yield回来的值也登月直接给了调用者。意思就是nwe_outer委托gen_yield工作。
- 当new_outer实例调用send方法,就等于gen_yield子迭代器同步调用send方法,把值send到子迭代器内部yield。
- 当子迭代器gen_yield内部捕获到StopIteration时,子迭代器内部停止执行,开始执行委托者new_outer.
- 委托生成器有一个 throw() 方法可发送任何除了 GeneratorExit 的异常都将被直接发送给子迭代器 。同理,如果这次调用产生了 StopIteration 异常,那么委托生成器 new_outer 将被恢复执行
- 如果向委托生成器发送了 GeneratorExit 异常或者调用委托生成器的 close() 方法,那么首先子迭代器 b 的 close() 方法就会被调用(如果有的话)。随后,委托生成器就会引发 GeneratorExit 异常,从而退出
- 如果迭代器 gen_yield中有 return value ,那么当 子迭代器 执行 return 返回时,等价于 raise StopIteration(value)(迭代器总是通过引发StopIteration 异常停止),之后该 value 将成为 yield from 表达式值。
- 在任意运行时刻,如果迭代器gen_yield抛出了未捕获的异常,那么该异常将会被传播给委托生成器new_outer
>>> def inner_gen():
... sum_all = 0
... while True:
... x = yield
... print('recv : {0}'.format(x))
... if x is None:
... return sum_all
... sum_all = sum_all + x
...
>>> def outer():
... while True:
... sum_all = yield from inner_gen()
... print('sum_all is: {0}'.format(sum_all))
... print('outer 执行完毕')
...
>>> out = outer()
>>> out.send(None) # 准备好协程
>>> for i in range(3):
... out.send(i)
...
recv: 0
recv: 1
recv: 2
>>> out.send(None) # 停止子协程
recv : None
sum_all is: 3
outer 执行完毕
>>> for i in range(5):
... out.send(i)
...
recv: 0
recv: 1
recv: 2
recv: 3
recv: 4
>>> out.send(None)
recv: None
sum_all is: 10
outer 执行完毕
>>> out.throw(TypeError) # TypeError 来自 inner_gen 函数
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in outer
File "<stdin>", line 4, in inner_gen
TypeError
使用 send() 方法发送的值将被直接发送字生成器 inner_gen() 中了,throw() 同理。当子迭代器返回时,return 后的值成为 yield from 表达式的值。
yield from 允许外界与子协程直接交互,这样就允许代码重构:把一部分包含 yield 的代码放到另外的函数,再使用 yield from 调用该迭代器。这样就实现委托工作了
yield from的更多相关文章
-
Python 生成器与迭代器 yield 案例分析
前几天刚开始看 Python ,后因为项目突然到来,导致Python的学习搁置了几天.然后今天看回Python 发现 Yield 这个忽然想不起是干嘛用的了(所以,好记性不如烂笔头.).然后只能 花点 ...
-
node 异步回调解决方法之yield
先看如何使用 使用的npm包为genny,npm 安装genny,使用 node -harmony 文件(-harmony 为使用es6属性启动参数) 启动项目 var genny= require( ...
-
yield生成器及字符串的格式化
一.生成器 def ran(): print('Hello world') yield 'F1' print('Hey there!') yield 'F2' print('goodbye') yie ...
-
Python中的生成器与yield
对于python中的yield有些疑惑,然后在*上看到了一篇回答,所以搬运过来了,英文好的直接看原文吧. 可迭代对象 当你创建一个列表的时候,你可以一个接一个地读取其中的项.一 ...
-
Python yield函数理解
Python中的yield函数的作用就相当于一个挂起,是不被写入内存的,相当于一个挂起的状态,用的时候迭代,不用的时候就是一个挂起状态,挂起状态会以生成器的状态表现
-
ecma6 yield
function * generator(k){ console.log('begin'); var x = yield k; console.log('x:',x); var y = yield x ...
-
Python yield与实现
Python yield与实现 yield的功能类似于return,但是不同之处在于它返回的是生成器. 生成器 生成器是通过一个或多个yield表达式构成的函数,每一个生成器都是一个迭代器(但是迭 ...
-
可惜Java中没有yield return
项目中一个消息推送需求,推送的用户数几百万,用户清单很简单就是一个txt文件,是由hadoop计算出来的.格式大概如下: uid caller 123456 12345678901 789101 12 ...
-
使用yield进行异步流程控制
现状 目前我们对异步回调的解决方案有这么几种:回调,deferred/promise和事件触发.回调的方式自不必说,需要硬编码调用,而且有可能会出现复杂的嵌套关系,造成"回调黑洞" ...
-
GetEnumerator();yield
GetEnumerator()方法的实质实现: 说明:只要一个集合点出GetEnumerator方法,就获得了迭代器属性,就可以用MoveNext和Current来实现foreach的效果,如上图. ...
随机推荐
-
Android Studio自动删除多余的import
在开发过程中,随着项目的迭代,文件内部分import 可能早已经不用了,对于这种无用的 import,我们不可能一个一个文件的删除.这里记录个自动删除无用import的功能. 一 .开发环境: And ...
-
linux Kernell crash dump------kdump 的安装设置+Linux系统崩溃的修复解决过程+mysql+kvm
http://www.ibm.com/developerworks/cn/linux/l-cn-dumpanalyse/https://www.kernel.org/pub/linux/utils/k ...
-
在 .pro里加入 QMAKE_CXXFLAGS += /MP 将并行编译,加快编译速度(姚冬的办法)
但是只对VC编译器有效果. 另外还可以自己设置stdafx.h文件 http://www.zhihu.com/question/23045749
-
Python 练习 —— 2048
1. 引言 2048 这段时间火的不行啊,大家都纷纷仿造,"百家争鸣",于是出现了各种技术版本号:除了手机版本号,还有C语言版.Qt版.Web版.java版.C#版等,刚好我接触P ...
-
linux和windows下,C/C++开发的延时函数,sleep函数
简介: 函数名: sleep 功 能: 执行挂起一段时间 用 法: unsigned sleep(unsigned seconds); 在VC中使用带上头文件 #include < ...
-
6. ZigZag Conversion (字符串的连接)
The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like ...
-
通过完整示例来理解如何使用 epoll
网络服务器通常使用一个独立的进程或线程来实现每个连接.由于高性能应用程序需要同时处理大量的客户端,这种方法就不太好用了,因为资源占用和上下文切换时间等因素影响了同时处理大量客户端的能力.另一种方法是在 ...
-
获取dataGridView双击时判断双击的是下面的行,还是列头
private void dataGridView1_DoubleClick(object sender, EventArgs e) { Point hit = this.dataGridView1. ...
-
2018科大讯飞AI营销算法大赛全面来袭,等你来战!
AI技术已成为推动营销迭代的重要驱动力.AI营销高速发展的同时,积累了海量的广告数据和用户数据.如何有效应用这些数据,是大数据技术落地营销领域的关键,也是检测智能营销平台竞争力的标准. 讯飞AI营销云 ...
-
sublime text 格式化html css 与显示函数列表
sublime 格式化html css 1.ctrl + shift + p 2.输入install package,选择install package 3.输入:HTML-CSS-JS Pretti ...