深入理解 Python yield
yield的英文单词意思是生产,刚接触Python的时候感到非常困惑,一直没弄明白yield的用法。一直到稀里糊涂的看完了廖雪峰的python博客也没彻底明白。
有一次不小心看到了这个文章,是转载的,原文出自哪里我也不知道,08年的文章,python2.5的,于是我按照3.6的标准重新定义一下,最后会附上源码
python2和python3是不兼容的,通篇环境都是python3.6
简单的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
应用的一个例子,但是,看过很多东西,并自己反复体验后,对yield有了一个全新的理解,其中这篇算是精品了。
包含yield的函数
假如你看到某个函数包含了yield
,这意味着这个函数已经是一个Generator
,它的执行会和其他普通的函数有很多不同。比如下面的简单的函数:
def h():print('study yield')yield 5print('go on!')h()
可以看到,调用h()
之后,print 语句并没有执行!这就是yield
。具体的内容后面会越来越清晰,包括yield
的工作原理。
yield是一个表达式
python 2.5以前,yield
是一个语句,我也没有考证,因为早都不用了,现在yield
是一个表达式:
m = yield 5
表达式(yield 5)的返回值将赋值给m,所以,m = 5
肯定是错的。
那么如何获取(yield 5)的返回值呢?需要用到send(msg)
。
yield工作原理
揭晓yield
的工作原理,需要配合next()
函数。上面的h()
被调用后并没有执行,因为它有yield
表达式,通过next()
可以恢复Generator
执行,直到下一个yield
。
def h():print('study yield')yield 5print('go on!')c = h()
d1 = next(c) # study yield
d2 = next(c)
"""
study yield
go on!
Traceback (most recent call last):File "D:/idea/workspace/pythonSpace/PythonDemo/static/yield_demo.py", line 35, in <module>d2 = next(c)
StopIteration
"""
next()
被调用后,h()
开始执行,直到遇到yield 5
因此输出结果是:study yield
当我们再次调用next()
时,会继续执行,直到找到下一个yield
。由于后面没有yield
了,因此会拋出异常:
study yield
go on!
Traceback (most recent call last):File "D:/idea/workspace/pythonSpace/PythonDemo/static/yield_demo.py", line 35, in <module>d2 = next(c)
StopIteration
send(msg) 与 next()
了解了next()
如何让包含yield
的函数执行后,我们再来看另外一个非常重要的函数send(msg)
。
其实next()
和send()
在一定意义上作用是相似的
区别
send()
可以传递yield
的值
next()
只能传递None
。
所以next()
和 send(None)
作用是一样的。
def s():print('study yield')m = yield 5print(m)d = yield 16print('go on!')c = s()
s_d = next(c) # 相当于send(None)
c.send('Fighting!') # (yield 5)表达式被赋予了'Fighting!'
输出的结果为:
study yield
Fighting!
注意 生成器刚启动时(第一次调用),请使用next()
语句或是send(None)
,不能直接发送一个非None的值,否则会报TypeError
,因为没有yield
语句来接收这个值。
send(msg) 与 next()的返回值
send(msg)
和 next()
的返回值比较特殊,是下一个yield
表达式的参数(yield 5,则返回 5)。
到这里,第一个例子中,通过for i in alist
遍历 Generator
,其实是每次都调用了next()
,而每次next()
的返回值正是yield
的参数:
def s():print('study yield')m = yield 5print(m)d = yield 16print('go on!')c = s()
s_d1 = next(c) # 相当于send(None)
s_d2 = c.send('Fighting!') # (yield 5)表达式被赋予了'Fighting!'
print('My Birth Day:', s_d1, '.', s_d2)
输出结果:
study yield
Fighting!
My Birth Day: 5 . 16
中断Generator
上面的例子中,当没有可执行程序的时候,会抛出一个StopIteration
, 开发过程中,中断Generator是一个非常灵活的技巧
throw
通过抛出一个GeneratorExit异常来终止Generator。
close
close的作用和throw是一样的,看它的源码,可以发现,它和raise一球样
def throw(self, type, value=None, traceback=None):'''Used to raise an exception inside the generator.'''# 用于在生成器中抛出一个异常。passdef close(self):'''Raises new GeneratorExit exception inside the generator to terminate the iteration.'''# 在生成器中生成新的GeneratorExit异常来终止迭代。pass
其实最后一个中断生成器可以忽略的,在开发过程中,不可避免的要用到这些,但是Python3内部已经做得很好了,一般不太需要手动去做这件事情。
demo地址
https://github.com/seeways/PythonDemo/blob/master/static/yield_demo.py
深入理解 Python yield相关推荐
- python yield理解_对Python中Yield的理解
看到下面这段程序的时候,有点不明白这个yield到底是个啥东西,看了网上很多的博客,大致理解了yield的含义,所以记录下来. 要说yield首先要说python中的生成器,那么什么是生成器? 假设有 ...
- 彻底理解Python中的yield
阅读别人的python源码时碰到了这个yield这个关键字,各种搜索终于搞懂了,在此做一下总结: 通常的for...in...循环中,in后面是一个数组,这个数组就是一个可迭代对象,类似的还有链表,字 ...
- 深入理解Python中的yield和send
send方法和next方法唯一的区别是在执行send方法会首先把上一次挂起的yield语句的返回值通过参数设定,从而实现与生成器方法的交互. 但是需要注意,在一个生成器对象没有执行next方法之前,由 ...
- 理解Python中的yield
理解Python中的yield 参考文献 本文浅谈自己对Python中yield关键字的理解. yield可以理解成return,但是它与return又不完全相同.在Python中,yield关键字是 ...
- 深入理解Python的With-as语句
学习Python有一段时间了,最近做一个项目会涉及到文件的读取和关闭.比如:我想把一些对象序列化到文件里面,然后当我再次使用的时候,在从文件里面读取反序列化成对象.像这种操作一般都是用try-exce ...
- c++ 协程_理解Python协程(Coroutine)
由于GIL的存在,导致Python多线程性能甚至比单线程更糟. GIL: 全局解释器锁(英语:Global Interpreter Lock,缩写GIL),是计算机程序设计语言解释器用于同步线程的一种 ...
- python3 协程 写法_理解Python的协程(Coroutine)
由于GIL的存在,导致Python多线程性能甚至比单线程更糟. GIL: 全局解释器锁(英语:Global Interpreter Lock,缩写GIL),是计算机程序设计语言解释器用于同步线程的一种 ...
- python在线搭建教程_理解python web开发,轻松搭建web app!
大家好,今天分享给大家的是理解python web开发,轻松搭建web app,希望大家学有所获! 因为 python代码的优雅美观且易于维护这一特点,越来越多的人选择使用 Python做web开发. ...
- python iterable对象_如何理解Python中的iterable对象
转载请注明出处:https://www.jianshu.com/u/5e6f798c903a [^*] 表示注脚,在文末可以查看对应连接,但简书不支持该语法. 首先,容器和 iterable 间没有必 ...
最新文章
- 206. Reverse Linked List
- springboot 集成mybatis时日志输出
- AOP 中必须明白的概念-目标对象(Target Object)
- 如何将bing搜索页面以HTML Mashup的方式嵌入到SAP C4C页面
- Android之mediarecorder中的方法以及工作流程的过程
- Python学习1——Python中的 split() 函数
- 被指涉嫌“二选一” 山姆回应:欢迎良性竞争
- python爬虫爬取豆瓣电影
- Es6 filter()、map()、find()方法详解
- Android Studio中竟然还能加入一个程序员鼓励师
- php爬虫入门之phpspider框架
- 逻辑回归实现文本分类
- 随心所遇,随遇而安。
- java-php-python-ssm网上游戏商店设计计算机毕业设计
- 计算机科学家手抄报图片,关于简洁又漂亮的科学手抄报图片
- python3删除重复文件,可用命令行
- ride.py在运行python3.×版本后导致无法运行及解决办法
- 【数学】三角函数小题
- APS54083 DC/DC升降压恒流驱动芯片 2.4G调光 —提供DEMO板
- Neural Voice Puppetry阅读笔记
热门文章
- qq公众平台出错了609_微信附近人功能无法使用,到底是平台出了差错还是由于自我原因。...
- 11GR2 中的常见 RMAN 问题
- 电脑为什么会蓝屏的原因
- 这个城市最安静的声音 - Suzy
- Berzerk CodeForces - 787C (BFS)题解
- Kitty: 又一款基于 GPU 加速的终端工具
- Windows:MULTIPROCESSOR CONFIGURATION NOT SUPPORTED蓝屏(32位(win10/LTSC 2019/LTSC 2021))
- 论文总结 -论文写作注意事项(持续更)
- 如果不做测试了,自己还能干点啥?
- 会动的小狗纯HTML代码