Python 深入理解yield
只是粗略的知道yield可以用来为一个函数返回值塞数据,比如下面的例子:
取出alist的每一项,然后把i + 1塞进去。然后通过调用取出每一项:
for x in addlist(alist):
print x,
这的确是yield应用的一个例子,但是,看过limodou的文章《2.5版yield之学习心得》,并自己反复体验后,对yield有了一个全新的理解。
1. 包含yield的函数
假如你看到某个函数包含了yield,这意味着这个函数已经是一个Generator,它的执行会和其他普通的函数有很多不同。比如下面的简单的函数:
yield 5
h()
可以看到,调用h()之后,print 语句并没有执行!这就是yield,那么,如何让print 语句执行呢?这就是后面要讨论的问题,通过后面的讨论和学习,就会明白yield的工作原理了。
2. yield是一个表达式
Python2.5以前,yield是一个语句,但现在2.5中,yield是一个表达式(Expression),比如:
表达式(yield 5)的返回值将赋值给m,所以,认为 m = 5 是错误的。那么如何获取(yield 5)的返回值呢?需要用到后面要介绍的send(msg)方法。
3. 透过next()语句看原理
现在,我们来揭晓yield的工作原理。我们知道,我们上面的h()被调用后并没有执行,因为它有yield表达式,因此,我们通过next()语句让它执行。next()语句将恢复Generator执行,并直到下一个yield表达式处。比如:
yield 5
print 'Fighting!'
c = h()
c.next()
c.next()调用后,h()开始执行,直到遇到yield 5,因此输出结果:
Wen Chuan
当我们再次调用c.next()时,会继续执行,直到找到下一个yield表达式。由于后面没有yield了,因此会拋出异常:
c.next()
StopIteration
4. send(msg) 与 next()
了解了next()如何让包含yield的函数执行后,我们再来看另外一个非常重要的函数
send(msg)。其实next()和send()在一定意义上作用是相似的,区别是send()可以传递yield表达式的值进去,而next()不
能传递特定的值,只能传递None进去。因此,我们可以看做
c.next() 和 c.send(None) 作用是一样的。
来看这个例子:
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语句来接收这个值。
5. send(msg) 与 next()的返回值
send(msg) 和
next()是有返回值的,它们的返回值很特殊,返回的是下一个yield表达式的参数。比如yield 5,则返回 5
。到这里,是不是明白了一些什么东西?本文第一个例子中,通过for i in alist 遍历
Generator,其实是每次都调用了alist.Next(),而每次alist.Next()的返回值正是yield的参数,即我们开始认为被压进
去的东东。我们再延续上面的例子:
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
6. throw() 与 close()中断 Generator
中断Generator是一个非常灵活的技巧,可以通过throw抛出一个GeneratorExit异常来终止Generator。Close()方法作用是一样的,其实内部它是调用了throw(GeneratorExit)的。我们看:
self.throw(GeneratorExit)
except (GeneratorExit, StopIteration):
pass
else:
raise RuntimeError("generator ignored GeneratorExit")
# Other exceptions are not caught
因此,当我们调用了close()方法后,再调用next()或是send(msg)的话会抛出一个异常:
d = c.send('Fighting!') #d 获取了yield 12 的参数值12
StopIteration
[转载]www.jb51.net/article/15717.htm
Python 深入理解yield的更多相关文章
- Python深入理解yield
yield的英文单词意思是生产,刚接触Python的时候感到非常困惑,一直没弄明白yield的用法. 只是粗略的知道yield可以用来为一个函数返回值塞数据,比如下面的例子: def addlist( ...
- Python天天美味(25) - 深入理解yield
Python天天美味(25) - 深入理解yield - CoderZh - 博客园 Python天天美味(25) - 深入理解yield yield的英文单词意思是生产,刚接触Python的时候 ...
- 深入理解Python中的yield和send
send方法和next方法唯一的区别是在执行send方法会首先把上一次挂起的yield语句的返回值通过参数设定,从而实现与生成器方法的交互. 但是需要注意,在一个生成器对象没有执行next方法之前,由 ...
- 深入理解python中的yield关键字
想必大家都看过这样的代码: 上面的这段代码会计算0-9的平方并打印出来. 那么问题来了,这段代码和我们要说的东西有什么区别呢? 这里的关键字,yield,我在前面的文章里已经发过了.那么yield是什 ...
- python中的yield
在理解yield之前,要首先明白什么是generator,在理解generator之前首先要理解可迭代的概念. 可迭代(iterables)在你创建一个list的时候,可以逐个读取其中的元素,该逐个读 ...
- 深入浅出理解yield
索引 转载部分内容来自:http://www.jianshu.com/p/d09778f4e055 [彻底理解yield] http://blog.csdn.net/haskei/article/de ...
- 深入理解yield(二):yield与协程
转自:http://blog.beginman.cn/blog/133/ 协程概念 1.并发编程的种类:多进程,多线程,异步,协程 2.进程,线程,协程的概念区别: 进程.线程和协程的理解 进程:拥有 ...
- 深入理解yield(三):yield与基于Tornado的异步回调
转自:http://beginman.cn/python/2015/04/06/yield-via-Tornado/ 作者:BeginMan 版权声明:本文版权归作者所有,欢迎转载,但未经作者同意必须 ...
- python协程--yield和yield from
字典为动词“to yield”给出了两个释义:产出和让步.对于 Python 生成器中的 yield 来说,这两个含义都成立.yield item 这行代码会产出一个值,提供给 next(...) 的 ...
随机推荐
- Oracle数据库自动启动Shell脚本
为了保证Oracle在下次系统重启后,能自动启动服务,这里我们可以通过一个Shell脚步来实现这个功能.假定脚步名称为/app/oracle/oraclestart.sh,其内容如下: #!/bi ...
- apache结合svn创建svn资源库
1.在登录过程中可以查看error日志,如果发生以下提示: (13)Permission denied: Could not open password file 2.运行:chcon -R -h - ...
- SPFA+寻路(行路难,洛谷2832)
啊啊啊这道难题总算是做出来了,首先是帅比浮云的题解发出来一下:http://www.cnblogs.com/fuyun-boy/p/5922742.html 原题目地址:https://www.luo ...
- Office组件之Spire.XLS的DotNet操作
Overview 在项目中,我们经常需要将程序中获得的大量数据导出到Excel表格中,打印报表:进一步,还可能生成其折线图,对数据的变化趋势进行分析,从而更好地开展项目工作. 最近,我发现了一个对于D ...
- 第四章 springboot + swagger(转载)
此篇博客转发自:http://www.cnblogs.com/java-zhao/p/5348113.html swagger用于定义API文档. 好处: 前后端分离开发 API文档非常明确 测试的时 ...
- 【如何快速的开发一个完整的iOS直播app】(原理篇)
原文转自:袁峥Seemygo 感谢分享.自我学习 目录 [如何快速的开发一个完整的iOS直播app](原理篇) [如何快速的开发一个完整的iOS直播app](播放篇) [如何快速的开发一个完整的 ...
- SQL脚本IN在EF中的应用
C#查询条件中存在in,为了避免拼脚本,参数化查询数据库,提高安全性,规避脚本注入.网上找了好多,最后发现 SqlParameter 是无法实现in的操作,所以只能变相来实现,结果还是不错的,性能上各 ...
- 转载:JAVA中关于set()和get()方法的理解及使用
对于JAVA初学者来说,set和get这两个方法似乎已经很熟悉了,这两个方法是JAVA变成中的基本用法,也是出现频率相当高的两个方法. 为了让JAVA初学者能更好的理解这两个方法的使用和意义,今天笔者 ...
- LINQ - 在Where條件式中使用in與not in
希望对大家在以后的项目中能用到,我也是在项目中碰到了这个问题: 算算時間,接觸LINQ也有一個月的時間了,可以算是落伍兼新生,不過最近在寫專案的時候,遇到了在LINQ的Where條件式中要如何使用in ...
- html5新特性之画布
1.canvas的理解 canvas是一个矩形区域,在这个区域内,通过js可以对区域内的每一帧像素控制 2.js操作canvas对象 canvas对象.getContext("2d" ...