yield的英文单词意思是生产,有时候感到非常困惑,一直没弄明白yield的用法。

只是粗略的知道yield可以用来为一个函数返回值塞数据,比如下面的例子:

def addlist(alist):
for i in alist:
yield i + 1

取出alist的每一项,然后把i + 1塞进去。然后通过调用取出每一项:

alist = [1, 2, 3, 4]
for x in addlist(alist):
print x,

这的确是yield应用的一个例子

1. 包含yield的函数

假如你看到某个函数包含了yield,这意味着这个函数已经是一个Generator,它的执行会和其他普通的函数有很多不同。比如下面的简单的函数:

def h():
print 'To be brave'
yield 5
h()

可以看到,调用h()之后,print 语句并没有执行!因为h()返回的是可迭代对象(iterable),使用迭代器才能执行,这就是yield。那么,如何让print 语句执行呢?这就是后面要讨论的问题,通过后面的讨论和学习,就会明白yield的工作原理了。

2. 透过next()语句看原理

现在,我们来揭晓yield的工作原理。我们知道,我们上面的h()被调用后并没有执行,因为它有yield表达式,因此,我们通过next()语句让它执行。next()语句将恢复Generator执行,并直到下一个yield表达式处。比如:

def h():
print 'Wen Chuan'
yield 5
print 'Fighting!'
c = h()
c.next()

c.next()调用后,h()开始执行,直到遇到yield 5,因此输出结果:

Wen Chuan

当我们再次调用c.next()时,会继续执行,直到找到下一个yield表达式。由于后面没有yield了,因此会拋出异常:

Wen Chuan
Fighting!
Traceback (most recent call last):
File "/home/evergreen/Codes/yidld.py", line 11, in <module>
c.next()
StopIteration

3. send(msg) 与 next()

了解了next()如何让包含yield的函数执行后,我们再来看另外一个非常重要的函数send(msg)。其实next()和send()在一定意义上作用是相似的,区别是send()可以传递yield表达式的值进去,而next()不能传递特定的值,只能传递None进去。因此,我们可以看做

c.next() 和 c.send(None) 作用是一样的。

来看这个例子:

def h():
print 'Wen Chuan',
m = yield 5 # Fighting!
print m
d = yield 12
print 'We are together!'
c = h()
c.next() #相当于c.send(None)
c.send('Fighting!') #(yield 5)表达式被赋予了'Fighting!'

输出的结果为:

Wen Chuan Fighting!

需要提醒的是,第一次调用时,请使用next()语句或是send(None),不能使用send发送一个非None的值,否则会出错的,因为没有yield语句来接收这个值。

4. send(msg) 与 next()的返回值

send(msg) 和 next()是有返回值的,它们的返回值很特殊,返回的是下一个yield表达式的参数。比如yield 5,则返回 5 。到这里,是不是明白了一些什么东西?本文第一个例子中,通过for i in alist 遍历 Generator,其实是每次都调用了alist.Next(),而每次alist.Next()的返回值正是yield的参数,即我们开始认为被压进去的东东。我们再延续上面的例子:

def h():
print 'Wen Chuan',
m = yield 5 # Fighting!
print m
d = yield 12
print 'We are together!'
c = h()
m = c.next() #m 获取了yield 5 的参数值 5
d = c.send('Fighting!') #d 获取了yield 12 的参数值12
print 'We will never forget the date', m, '.', d

输出结果:

Wen Chuan Fighting!
We will never forget the date 5 . 12

5. throw() 与 close()中断 Generator

中断Generator是一个非常灵活的技巧,可以通过throw抛出一个GeneratorExit异常来终止Generator。Close()方法作用是一样的,其实内部它是调用了throw(GeneratorExit)的。我们看:

def close(self):
try:
self.throw(GeneratorExit)
except (GeneratorExit, StopIteration):
pass
else:
raise RuntimeError("generator ignored GeneratorExit")
# Other exceptions are not caught

因此,当我们调用了close()方法后,再调用next()或是send(msg)的话会抛出一个异常:

Traceback (most recent call last):
File "/home/evergreen/Codes/yidld.py", line 14, in <module>
d = c.send('Fighting!') #d 获取了yield 12 的参数值12
StopIteration

Python yield详解***的更多相关文章

  1. Python Collections详解

    Python Collections详解 collections模块在内置数据结构(list.tuple.dict.set)的基础上,提供了几个额外的数据结构:ChainMap.Counter.deq ...

  2. python生成器详解

    1. 生成器 利用迭代器(迭代器详解python迭代器详解),我们可以在每次迭代获取数据(通过next()方法)时按照特定的规律进行生成.但是我们在实现一个迭代器时,关于当前迭代到的状态需要我们自己记 ...

  3. Python闭包详解

    Python闭包详解 1 快速预览 以下是一段简单的闭包代码示例: def foo(): m=3 n=5 def bar(): a=4 return m+n+a return bar >> ...

  4. [转] Python Traceback详解

    追莫名其妙的bugs利器-mark- 转自:https://www.jianshu.com/p/a8cb5375171a   Python Traceback详解   刚接触Python的时候,简单的 ...

  5. python 数据类型详解

    python数据类型详解 参考网址:http://www.cnblogs.com/linjiqin/p/3608541.html 目录1.字符串2.布尔类型3.整数4.浮点数5.数字6.列表7.元组8 ...

  6. Python 递归函数 详解

    Python 递归函数 详解   在函数内调用当前函数本身的函数就是递归函数   下面是一个递归函数的实例: 第一次接触递归函数的人,都会被它调用本身而搞得晕头转向,而且看上面的函数调用,得到的结果会 ...

  7. python线程详解

    #线程状态 #线程同步(锁)#多线程的优势在于可以同时运行多个任务,至少感觉起来是这样,但是当线程需要共享数据时,可能存在数据不同步的问题. #threading模块#常用方法:'''threadin ...

  8. python数据类型详解(全面)

    python数据类型详解 目录1.字符串2.布尔类型3.整数4.浮点数5.数字6.列表7.元组8.字典9.日期 1.字符串1.1.如何在Python中使用字符串a.使用单引号(')用单引号括起来表示字 ...

  9. 转 python数据类型详解

    python数据类型详解 目录 1.字符串 2.布尔类型 3.整数 4.浮点数 5.数字 6.列表 7.元组 8.字典 9.日期 1.字符串 1.1.如何在Python中使用字符串 a.使用单引号(' ...

随机推荐

  1. Michael-Scott非阻塞队列(lock-free)算法的C实现

    Michael-Scott非阻塞队列算法,即MS-queue算法,是1 9 9 6 年由Maged . M .Michael and M. L. Scott提出的,是最为经典的并发FIFO队列上的算法 ...

  2. SDOI2018划水记

    DAY -1 明天就要走了,今天就怎么也提不起兴趣来做题了.花了一个上午研究如何搞背景动画结果华丽丽失败了,为什么我自己设置的时候动画会在最上层啊(呜呜~~.下午随便打了板子又开始颓废了,然后看生蚝还 ...

  3. LA 3942 背单词

    https://vjudge.net/problem/UVALive-3942 题意: 给出一个由S个不同单词组成的字典和一个长字符串.把这个字符串分解成若干个单词的连接,有多少种方法?比如,有4个单 ...

  4. 学习maven,看思维导图就够了

    一直在用 Mindjet MindManager和xmind 做思维导图.以前在用思维导图写读书笔记时,总是想要事无巨细地写清楚每个知识点,现在想来是事倍功半.思维导图应该是一个帮助我们梳理知识点.理 ...

  5. 解决点击tomcat的startup.bat一闪而过的问题

    问题: 点击startup.bat一闪而过,经过网上查询,原来是没有配置JAVA_HOME,配置一下就可以了 原因: tomcat在启动时,会读取环境变量的信息,需要一个CATALINA_HOME 与 ...

  6. bzoj1084: [SCOI2005]最大子矩阵 dp

    这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. 题解:m很小分类讨论,m==1时怎么搞都可以,m==2时,dp[i][j][k]表 ...

  7. hdu 5303 DP(离散化,环形)+贪心

    题目无法正常粘贴,地址:http://acm.hdu.edu.cn/showproblem.php?pid=5303 大意是给出一个环形公路,和它的长度,给出若干颗果树的位置以及树上的果子个数. 起点 ...

  8. C#对象初始或器-Chapter3 P38

    protected string GetMessage() { //如何构造和初始化泛型集合库中的一个数组和两个类. Product myProduct = ,Name="Kayak&quo ...

  9. [转载]c语言指针segmentation fault 指针常常错误的小地方

    http://www.cnblogs.com/qingjoin/archive/2012/03/20/2408944.html #include <stdio.h> ] = ] = ] = ...

  10. 009PHP文件处理——文件处理 file_get_contents file_put_contents fgetc fgets fgetss

    <?php /** * 文件处理 file_get_contents file_put_contents fgetc fgets fgetss */ //fgetc() 传入文件操作句柄.每次获 ...