本篇博客转载了点击打开链接,又加上了自己的一点理解

深入理解yield

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

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

1
2
3
def  addlist(alist):
     for  in  alist:
         yield  +  1

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

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

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

1. 包含yield的函数

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

1
2
3
4
def  h():
     print  'To be brave'
     yield  5
h()

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

2. yield是一个表达式

Python2.5以前,yield是一个语句,但现在2.5中,yield是一个表达式(Expression),比如:

m = yield 5

表达式(yield 5)的返回值将赋值给m,所以,认为 m = 5 是错误的。那么如何获取(yield 5)的返回值呢?需要用到后面要介绍的send(msg)方法。

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

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

1
2
3
4
5
6
def  h():
     print  'Wen Chuan'
     yield  5
     print  'Fighting!'
=  h()
c. next ()

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

Wen Chuan

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

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

4. send(msg) 与 next()

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

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

来看这个例子:

1
2
3
4
5
6
7
8
9
def  h():
     print  'Wen Chuan' ,
     =  yield  5   # Fighting!
     print  m
     =  yield  12
     print  'We are together!'
=  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的参数,即我们开始认为被压进去的东东。我们再延续上面的例子:

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

输出结果:

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

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

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

1
2
3
4
5
6
7
8
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)的话会抛出一个异常:

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

调用next()函数返回的是yield后面的值,yield表达式的值不是yield后面跟着的东西,而是通过send()函数传入进去的值,传入的值赋值给当前yield表达式的值,详细见下面代码

def f():print('start')a = yield 1print(a)print('middle....')b = yield 2 #2这个值只是迭代值,调用next时候返回的值print(b) #传入的参数是给当前yield的,也就是yield 2,因为当前函数走到了yield 2,所以传入的参数没有给yield 1print('next')c = yield 3print(c)a = f()
next(a)
next(a)
a.send('msg')

结果是:

start
None
middle....
msg
next
[Finished in 0.2s]

python3 yield相关推荐

  1. python3 yield 大文件_详解Python3中yield生成器的用法

    任何使用yield的函数都称之为生成器,如: def count(n): while n > 0: yield n #生成值:n n -= 1 另外一种说法:生成器就是一个返回迭代器的函数,与普 ...

  2. python3 yield和iter的区别_Python中的yield关键字

    Yield? 总的来说,yield关键字和return关键字有相似之处,但其工作机制却大相径庭.想要完整地理解yield的工作机制,我们首先需要明白什么是generator.而为了明白什么是gener ...

  3. python3 yield from用法

    原文:http://www.cnblogs.com/cdma/p/6839640.html #说明:yield from iterable本质上等于for item in iterable: yiel ...

  4. Python3迭代器和生成器

    迭代器 迭代是Python最强大的功能之一,是访问元素集合的一种方法. 迭代器是一个可以记住遍历的位置的对象. 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束,迭代器只能向前不会后退 ...

  5. python全数字问题_关于python:获取一个数字的所有除数的最佳方法是什么?

    这是非常愚蠢的方式: 1 2 3 4def divisorGenerator(n): for i in xrange(1,n/2+1): if n%i == 0: yield i yield n 我想 ...

  6. Python3中的yield from语法

    Python3中的yield from语法 by Kay Zheng  Tags: python, 协程, generator  30 March 2014 2016-2-23 更新 這篇文章是兩年前 ...

  7. 详解Python3中yield生成器的用法

    这篇文章主要介绍了详解Python3中yield生成器的用法,是Python入门学习中的基础知识,需要的朋友可以参考下 任何使用yield的函数都称之为生成器,如: def count(n):whil ...

  8. python3可迭代对象、迭代器、生成器、协程yield入门

    #!/usr/bin/env python # -*- coding: utf-8 -*- # @Date : 2019-01-24 16:13:07 # @Author : cdl (1217096 ...

  9. yield python3 知乎_运维学python之爬虫高级篇(七)scrapy爬取知乎关注用户存入mongodb...

    首先,祝大家开工大吉! 本篇将要介绍的是从一个用户开始,通过抓关注列表和粉丝列表,实现用户的详细信息抓取并将抓取到的结果存储到 MongoDB. 1 环境需求 基础环境沿用之前的环境,只是增加了Mon ...

最新文章

  1. 广东线上比赛过程集锦
  2. 机器学习(MACHINE LEARNING) 【周志华版-”西瓜书“-笔记】 DAY16-强化学习
  3. 【BIEE】BIEE报表根据维度表展示事实表不存在的维度
  4. tomcat的wget链接_Linux(jdk安装tomcat安装nginx安装gcc/wget)
  5. 热敏电阻温度特性曲线_热敏电阻与体温计的应用关系
  6. 前端学习(1189):事件基本使用
  7. [原]敏捷开发-项目启动
  8. 上次遗留下来的XMLUtil的问题
  9. nyoj1189 yougth和他的朋友们(滚动数组运用)
  10. 解决vscode的报错:Java 11 or more recent is required to run the Java extension
  11. CodeForces - 379A
  12. 51单片机-波特率的计算定时器初始值的计算
  13. 头歌平台数据结构与算法 单链表实验 第1关:倒置链表
  14. 定义一个数组存储10个上面描述的小怪兽,每个小怪兽的名字为(小怪兽+数组下标)
  15. PWNFEST黑客大会:苹果Safari与微软Edge浏览器均被攻破
  16. 掌握PS制作,实时预览你的精彩作品
  17. 计算机控制课程设计pid控制,自动化计算机控制课程设计参考题目
  18. ubuntu18.04安装Realsense D435i 摄像头的驱动SDK和ROS Wrapper
  19. 研发内控平台设计简介
  20. 调用微博分享sharesdk Unable to start activity ComponentInfo

热门文章

  1. SQL如何进行帕累托分析?(窗口函数、累计百分比分类)
  2. Box3 代码教程 (一)
  3. Excel保存文件不能直接打开,打开之后显示灰屏,从左上角的文件中,再找到要打开的文件才能打开?
  4. 在浏览器端浏览EPUB
  5. python演奏音乐
  6. inux中,如何把一个目录及其子目录中的读写权限交给一个普通用户!
  7. 中忻嘉业:抖音小店主要引流玩法
  8. git push 使用中遇到的Permission to xxx denied to xxx问题终极解决方案
  9. 可能是全网首个支持阿里云Elasticsearch Xapck鉴权的Skywalking
  10. php修改qq举报按钮,自定义修改QQ在线状态