设为首页 收藏本站
查看: 656|回复: 0

[经验分享] python中yield的分析

[复制链接]

尚未签到

发表于 2017-4-28 11:46:48 | 显示全部楼层 |阅读模式
  yield是Python中比较有意思,也比较有难度,我也是阅读代码的过程中发现了这个函数的好处,yield是生成的意思,但是在python中则是作为生成器理解,生成器的用处主要可以迭代,这样简化了很多运算模型。
  关于yield可以参看《Python 深入理解yieldhttp://www.iyunv.net/article/15717.htm》这篇文章中比较详细的描述了yield的基本原理和问题。
  yield在python2.5以后不再是一个句子,而是一个表达式,表达式是有返回值的,就如同我们在C语言中的if(expression)一样。
  当函数中存在yield以后,那么该函数就不在是普通的函数了,而是一个生成器。当该函数被调用时,并不会自动执行,而是暂停中,可以从下面的代码中得到体现。
  >>> def mygenerator():
  ... print 'start....'
  ... yield 5
  ...
  >>> mygenerator()
  <generator object mygenerator at 0xa2084b4>
  从上面的结果可以知道,在mygenerator()之后,并没有打印出starting....说明存在yield的函数被调用的时候是没有运行的,可以认为是暂停的状态,因此需要重新启动程序。这时采用next()即可实现函数的启动。
  >>> g = mygenerator()
  >>> g.next()
  start....
  5
  >>> g.next()
  Traceback (most recent call last):
  File "", line 1, in <module>
  StopIteration
  mygenerator()中创建了对象g,这时需要next()启动程序的运行,出现了上面的结果,也就是完成了程序的重新运行,但是遇到yield后就会再次停止,从上面的效果我们可以知道,在第一次运行g.next()之后,打印,然后遇到了yield 5,这时候就会停止,再次g.next()之后,后面没有yield,说明迭代过程结束,抛出了StopIteration异常。
  >>> def mygenerator2():
  ... print 'starting ....'
  ... yield 5
  ... print 'middle ....'
  ... yield 12
  ... print 'end ....'
  ...
  >>> g1 = mygenerator2()
  >>> g1.next()
  starting ....
  5
  >>> g1.next()
  middle ....
  12
  >>> g1.next()
  end ....
  Traceback (most recent call last):
  File "", line 1, in <module>
  StopIteration
  上面的代码也说明我的分析是正确的,第一次调用next()就执行到yield 5,暂停,然后next(),重新启动,并执行到yield 12,然后再次next()之后就会抛出错误,从上面打印出来的字符串就可知道。但输出中我们还发现了5,12等这是为什么呢?我认为这实质上是yield 5的返回值,因为表达式也会存在值的问题,这是肯定会输出表达式的值。
  那么这是否可以认为yield 5的返回值一定是5吗?实际上并不是这样,这个与send函数存在一定的关系,这个函数实质上与next()是相似的,区别是send是传递yield表达式的值进去,而next不能传递特定的值,只能传递None进去,因此可以认为g.next()和g.send(None)是相同的。
  >>> def mygenerator2():
  ... print 'starting ....'
  ... m = yield 5
  ... print m
  ... print 'middle ....'
  ... d = yield 12
  ... print d
  ... print 'end ....'
  ...
  >>> g1 = mygenerator2()
  >>> g1.next()
  starting ....
  5
  >>> g1.send('pass expression')
  pass expression
  middle ....
  12
  >>> g1.next()
  None
  end ....
  Traceback (most recent call last):
  File "", line 1, in <module>
  StopIteration
  >>> g1 = mygenerator2()
  >>> g1.next()
  starting ....
  5
  >>> g1.send('pass expression')
  pass expression
  middle ....
  12
  >>> g1.send('pass expression')
  pass expression
  end ....
  Traceback (most recent call last):
  File "", line 1, in <module>
  StopIteration
  从上面的效果可知道,可以知道,next()的传递的实质上就是None,而send传递进来的pass expression也作为表达式yield n的返回值,因此我们可以知道,yield的返回值并不是n的值,而是和send()传递进去的参数密切相关。实质上yield n表达式的返回值是指上就是send()函数传递进去的参数,了解到这一点是非常重要的。
  关于send()和next()函数的返回值也是需要我们详细去分析的,从下面的代码可以知道:
  >>> def returntest():
  ... m = yield 5
  ... print m
  ... n = yield 10
  ... print n
  ... h = yield 15
  ... print h
  ...
  >>> t = returntest()
  >>> n = t.next()
  >>> n
  5
  >>> n = t.next()
  None
  >>> n
  10
  >>> n = t.next()
  None
  >>> n
  15
  >>> t = returntest()
  >>> n = t.next()
  >>> n
  5
  >>> n = t.send(40)
  40
  >>> n
  10
  >>> n = t.send(50)
  50
  >>> n
  15
  从上面的代码我们可以知道next()和send()的返回值是与yield n的n密切相关,实际上就是yield n的n值。而yield的返回值就是send()传递进来的非None参数。
  有一段经典的代码是不得不去分析的:
  >>> def addlist(alist):
  ... for i in alist:
  ... yield i + 1
  ...
  这段代码中实际上就是运用了上面几个函数的返回值,因为for ...in句式实质上就是一个迭代器,也就是说alist = addlist.next(),采用next的返回值也就是yield n的参数值n,也就是完成了alist = i+1.这就是返回值的灵活运用,这段代码被灵活的运用于Python的迭代器中。
  总结:
  yield 的返回值是send(参数)中的参数,比如send(10),那么yield的返回值就是10
  send(None)和next()的意思是一样的,但是因为send不能传递None量,因此这才突显出了next()函数的作用,这两个函数的返回值通常就是yield n中的参数n。
  存在yield的函数不是普通的函数,而是生成器,只有调用send()或者next()函数以后才能执行,否则就是暂停的形式,这与其他函数是存在差别的。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-370390-1-1.html 上篇帖子: python 的log格式 下篇帖子: python之globals()和locals()
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表