yield

为了理解什么是 yield,你必须理解什么是生成器。在理解生成器之前,让我们先知道什么是迭代。

可迭代对象

当你建立了一个列表,你可以逐项地读取这个列表,这叫做一个可迭代对象:

>>> mylist = [1, 2, 3]
>>> for i in mylist :
...    print(i)
1
2
3

mylist 是一个可迭代的对象。当你使用一个列表生成式来建立一个列表的时候,就建立了一个可迭代的对象:

>>> mylist = [x*x for x in range(3)]
>>> for i in mylist :
...    print(i)
0
1
4

使用迭代器会把所有的值都存储到了内存中,如果你有大量数据的话这个方式并不是你想要的。

生成器

生成器是可以迭代的,但是你 只可以读取它一次 ,因为它并不把所有的值放在内存中,它是实时地生成数据

def get_yield(limit):for i in range(limit):yield it = get_yield(5)
print(t)
# t输出为 <generator object get_yield at 0x000001C69833CEB8>
for num in t:print(num)
# 下面这一段不会输出
for num in t:print(num)

yield和return很相似,都起到返回值的作用,但是yield所在的函数返回的是一个生成器,return则直接将某个变量返回,并退出函数。要知道,上面的get_yield函数并不是一被调用就马上执行,可以观看下段代码来更好地了解这一点。

import time
def oneByone(limit):for i in range(limit):print('oneByone里面i的值是:', i)yield it = oneByone(5)
for j in range(5):i = next(t)print(print('main函数里面i的值是:' , i)time.sleep(1)print(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))

输出结果:

oneByone里面i的值是: 0
main函数里面i的值是: 0
2018-07-30 12:40:54
oneByone里面i的值是: 1
main函数里面i的值是: 1
2018-07-30 12:40:55
oneByone里面i的值是: 2
main函数里面i的值是: 2
2018-07-30 12:40:56
oneByone里面i的值是: 3
main函数里面i的值是: 3
2018-07-30 12:40:57
oneByone里面i的值是: 4
main函数里面i的值是: 4
2018-07-30 12:40:58

具体理解可以参见高级用法部分的next方法

高级用法:

1.控制生成器的穷尽(摘自该文章)

>>> class Bank(): # let's create a bank, building ATMs
...    crisis = False
...    def create_atm(self) :
...        while not self.crisis :
...            yield "$100"
>>> hsbc = Bank() # when everything's ok the ATM gives you as much as you want
>>> corner_street_atm = hsbc.create_atm()
>>> print(next(corner_street_atm))
$100
>>> print(next(corner_street_atm))
$100
>>> print([next(corner_street_atm) for cash in range(5)])
['$100', '$100', '$100', '$100', '$100']
>>> hsbc.crisis = True # crisis is coming, no more money!
>>> print(next(corner_street_atm))
<type 'exceptions.StopIteration'>
>>> wall_street_atm = hsbc.create_atm() # it's even true for new ATMs
>>> print(next(wall_street_atm))
<type 'exceptions.StopIteration'>
>>> hsbc.crisis = False # trouble is, even post-crisis the ATM remains empty
>>> print(next(corner_street_atm))
<type 'exceptions.StopIteration'>
>>> brand_new_atm = hsbc.create_atm() # build a new one to get back in business
>>> for cash in brand_new_atm :
...    print cash
$100
$100
$100
$100
$100
$100
$100
$100
$100
...

这里面的逻辑是这么一回事:首先实现了一个Bank类,然后定义了类的所有实例共享的成员变量crisis,当crisis为False时,生成器create_atm()可迭代,反之不行。创建一个hsbc实例,首先创建corner_street_atm这个生成器,可以一直使用next(corner_street_atm)来迭代,但是一旦将crisis设为True,且再次调用next(corner_street_atm)时,该生成器就不可迭代了

注意,将crisis设置为True之后,一定要再次调用生成器该生成器才会不可迭代

这里的逻辑其实很好懂,为什么需要再次调用才会不可迭代呢?因为上面的函数并不会一次性执行完,而是使用next则执行一次,所以当你将crisis设置为True时,如果不使用next方法,则一直不会跳出while循环)。

2.send和next方法

python生成器有两个主要方法,一个是send一个是next。

在每段代码中,第一个next调用,相当于启动生成器,会从生成器函数的第一行代码开始执行,直到第一次执行完yield语句(第4行)后,跳出生成器函数。然后第二个next调用,进入生成器函数后,从yield语句的下一句语句(第5行)开始执行,然后重新运行到yield语句,执行后,跳出生成器函数后面再次调用next,依此类推。即执行一次next则调用一次生成器函数,直至抛出不可迭代的错误。

1 def consumer():
2     r = 0
3     for i in xrange(3):
4         yield r
5         r = '200 OK'+ str(i)
6
7 c = consumer()
8 n1 = c.next()
9 n2 = c.next()
10 n3 = c.next()

(该段代码摘自该文章)

send方法和next方法其实很相似,唯一的区别在于send方法可以传入值,而next方法不能传值,可以这样说,next(c) = c.send(None)

第一次调用时不能使用send发送一个非None的值,否则会出错的,因为没有Python yield语句来接收这个值。

def consumer():r = ''while True:n = yield r # Aif not n:returnprint('[CONSUMER] Consuming %s...' % n)r = '200 OK'def produce(c):c.send(None) # B n = 0while n < 5:n = n + 1print('[PRODUCER] Producing %s...' % n)r = c.send(n) # Cprint('[PRODUCER] Consumer return: %s' % r)c.close()c = consumer()
produce(c)

运行结果:

[PRODUCER] Producing 1...
[CONSUMER] Consuming 1...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 2...
[CONSUMER] Consuming 2...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 3...
[CONSUMER] Consuming 3...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 4...
[CONSUMER] Consuming 4...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 5...
[CONSUMER] Consuming 5...
[PRODUCER] Consumer return: 200 OK

在该段代码里面,首先是创建了生成器c,然后将c传入produce里面。下面开始讲解produce和consume函数的交互:

首先执行c.send(None),然后进入生成器函数里面,执行到A处(注意,此处没有执行赋值操作,遇见yield就跳回B了),然后从B的末尾继续执行,在C处执行r = c.send(1),然后又跳回到生成器函数的A处,那么send是怎么赋值的呢???这里是将(yield r)当做一个整体,然后将该值赋给n,也就是n=1了,继续执行A后面的语句,直至再次到A处,重复前面的步骤至循环结束。

另外,C处的语句r都会接受到生成器函数返回的r值。

3.yield from

https://www.cnblogs.com/cdma/p/6839640.html

https://blog.csdn.net/chenbin520/article/details/78111399?locationNum=7&fps=1

https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001432090954004980bd351f2cd4cc18c9e6c06d855c498000

python的yield和yield from相关推荐

  1. Python中yield和yield from的用法

    yield 后面接的是 future 对象 调用方 委托生成器 yield from 直接给出循环后的结果 yield from 委托者和子生成器直接通信 yield from 直接处理stopIte ...

  2. python yield from yield_python yield和yield from用法总结详解 python yield和yield from用法总结...

    #!/usr/bin/env python # -*- coding: utf-8 -*-from inspect import isgeneratorfunction def fab(max): n ...

  3. Python生成器实现及yield关键字

    Python生成器实现及yield关键字 我在另一篇文章中介绍了Python迭代器,https://blog.csdn.net/weixin_43790276/article/details/9034 ...

  4. python yield from_简述 yield 和 yield from

    yield 函数可以看成是一堆指令的集合.在函数中加入yield可以把一个函数变成一个generator,虽然调用的方式不一样了,但是其实现的功能和原来的函数基本是一样的. 而yield在这其中的作用 ...

  5. python协程--yield和yield from

    字典为动词"to yield"给出了两个释义:产出和让步.对于 Python 生成器中的 yield 来说,这两个含义都成立.yield item 这行代码会产出一个值,提供给 n ...

  6. 从yield 到yield from再到python协程

    yield 关键字 def fib():a, b = 0, 1while 1:yield ba, b = b, a+b yield 是在:PEP 255 -- Simple Generators 这个 ...

  7. python进阶:yield与yield from

    目录 yield与生成器 send close throw yield from yield与生成器 前面我们介绍过生成器:迭代器.可迭代对象.生成器的区别和联系 使用了 yield 的函数被称为生成 ...

  8. python学习——yield和yield from

    一.先来看看yield返回的是什么东东 yield关键字只能在函数中使用,否则会抛出语法异常 咱们知道只要在函数中存在yield关键字,那么这个在调用这个函数的时候,其返回值就是一个生成器对象,下图咱 ...

  9. 从yield到yield from

    yield 带有 yield 的函数不再是一个普通函数,而是一个生成器generator 把生成器当作管道 def add_A(seq):for item in seq:yield item + '- ...

  10. yield 和 yield*

    yield yield 关键字用来暂停和恢复一个生成器函数(function*) 举例: function* gen(index) {while (index < 2) {yield index ...

最新文章

  1. django前后端结合_一图看懂Django和DRF
  2. 验证二叉搜索树Python解法
  3. antd Datepicker组件报错 ——date.clone is not a function或者date1.isAfter is not a function
  4. STM32 定时器输出pwm的频率计算方法 PWM 频率检测方法 直流电机的位置控制
  5. Python 之 str 、 repr 、 反引号(``)的区别
  6. JDK获取所有的系统参数
  7. 华硕aura完全卸载_手感细腻,外观出色,配件良心、华硕TUF GAMING K7 光轴机械键盘...
  8. Http Headers为何物
  9. python转码时出现'illegal multibyte sequen'错误
  10. uvaLive 4490 Help Bubu 帮助布布 等价转化+DP
  11. 滚动 下拉简单实现分页
  12. (六)R语言生物序列比对——Needleman-Wunsch全局比对算法
  13. 过去一周区块链投融资事件回顾
  14. html调用wifi热点,笔记本如何做wifi热点
  15. MouseManager
  16. LB10S-ASEMI贴片整流桥LB10S
  17. Week9 作业——B - 东东学打牌
  18. 如何播放无限长度的音乐
  19. Java 读取TXT文件的多种方式-行读取,字节读取
  20. 手机怎么解压php文件夹,手机怎么解压文件

热门文章

  1. 26、Power Query-日期与时间数据处理实例(统计出某年各月各周的借书人数)
  2. T-SQL 编程之结果集循环处理
  3. 程序员眼中的英文单词竟是这样的
  4. Intel 酷睿i5 6300HQ与Intel 酷睿i7 6700HQ哪个好
  5. VF02 会计凭证过账时间
  6. redis的hGetAll函数的性能问题
  7. SAP Tax计算逻辑
  8. [FI] SAP 关于标准成本、计划成本、目标成本、实际成本
  9. ABAP内表(internal table)有关的系统变量
  10. 从“连锁”到“新联锁”,尚美生活如何引领酒店行业变革?