生成器不会吧结果保存在一个系列里,而是保存生成器的状态,在每次进行迭代时返回一个值,直到遇到StopTteration异常结束

1、生成器语法:

  生成器表达式:通列表解析语法,只不过把列表解析的[] 换成()

  生成器表达式能做的事情列表解析基本能处理,只不过在需要的序列比较大时,列表解析比较非内存

2、生成器函数:
  在函数中出现 yield 关键字,那么该函式就不在是普通的函数,而是生成器函数

  但是生成器函数可以生产一个无限的序列,这样列表根本没有办法进行处理

  yield 的作用就是把一个函数变成一个 generator ,带有 yield 的函数不再是一个普通的函数,Python 解释器会将其视为一个 generator

3、yield 与 return

  在一个生成器中,如果没有 return ,则默认执行到函数完毕时返回 StopTterration

def gen():
yield 'a' >>> g = gen()
>>> next(g)
traceback (most recent call last):
File"<stdin>", line , in <module>
StopIterration

  如果在执行的过程中遇到 return , 则直接抛出 StopIteration 终止迭代

def gen():
yield 'a'
return
yield 'b' >>>g = gen()
>>>next(g) # 程序停留在执行玩yield “a” 语句后的位置
‘a’
>>>next(g) # 程序发现下一条语句时return,所以抛出 StopTieration,这样 yield ‘b’ 语句永远不会执行
Traceback (most recent call last):
File"<stdin>", line , in <module>
StopIteraion

生成器支持的方法

1、close()

  手动关闭生成器,后面的调用会直接返回StopIteration 异常

>>>def gen():
yield
yield
yield >>>g = gen()
>>>next(g) >>>g.close() # 关闭后 yield 和 yield 语句将不会在起作用
Traceback (most call last):
File "<stdin>", line , in <module>
StopIteration

2、send()

  生成器函数最大的特点是可以接受外部传入一个变量,根据变量内容计算结果后返回

  这是生成器函数最难理解的地方,也是最重要的地方,携程就全靠他了

def gen():
value=
while True:
receive=yield value
if receive=='e':
break
value = 'got: %s' % receive g=gen()
print(g.send(None))
print(g.send('aaa'))
print(g.send())
print(g.send('e'))

执行流程:

  1、通过g.send(None) 或者 next(g) 可以启动器函数,并执行第一个 yield 语句结束的位置

    此时,执行完了 yield 语句,但是没有给 receive 赋值, yield value 会输出初始值0

  2、通过 g.send('aaa'),会传入 aaa, 并赋值给 receive ,然后计算value的值,并回到 while 头部,执行 yield value 语句有停止

    此时 yield value 会输出 ‘’got‘ aaa, 然后挂起

  3、通过 g.send(3), 会重复第二步,最后输出结果 为 “got:”3

  4、当我们 g.send('e') 时,程序执行break然后退出循环,最后整个函数执行完毕,所以会得到 StopItration异常

got: aaa
got:
Traceback (most recent call last):
File "h.py", line , in <module>
print(g.send('e'))
StopIteration

3、throw()

  用来向生成器函数送入一个异常,可以结束系统定义的异常,或者自定义的异常

  throw()后直接排除异常结束程序。或者消耗掉一个 yield,或者在没有下一个 yiled 的时候直接进行到程序的结尾

def gen():
while True:
try:
yield 'normal value'
yield 'normal value 2'
print('here')
except ValueError:
print('we got ValueError here')
except TypeError:
break g=gen()
print(next(g))
print(g.throw(ValueError))
print(next(g))
print(g.throw(TypeError))

输出结果为:

normal value
we got ValueError here
normal value
normal value
Traceback (most recent call last):
File "h.py", line , in <module>
print(g.throw(TypeError))
StopIteration

执行流程:

  1、print(next(g)): 会输出 Normal value,并停留在 yield ’normal value‘之前

  2、由于执行了 g.throw(TypeError), 所以会跳过所有后续的 try 语句,也就是说 “yield ’normal value2‘” 不会被执行,让后进入到 except 语句,打印出 we got ValueError here

    然后再次进入到while循环语句部分,消耗掉一个 yield ,所以会输出 normal value

  3,print(next(g)),会执行 yield normal value2  语句,并停留在下hi行语句后的位置

  4、g.throw(TypeError):会跳出 try 语句,从而 print(’here‘) 不会执行,跳出while循环,然后到达程序结尾,所以抛出 StopIteration 异常

综合例子,把一个多维列表展开,或者说扁平化多维列表

def flatten(nested):

    try:
#如果是字符串,那么手动抛出TypeError。
if isinstance(nested, str):
raise TypeError
for sublist in nested:
#yield flatten(sublist)
for element in flatten(sublist):
#yield element
print('got:', element)
except TypeError:
#print('here')
yield nested L=['aaadf',[,,],,,[,[,[,[]],'ddf'],]]
for num in flatten(L):
print(num)

4、yield from

  yield 产生的函数就是一个迭代器,所我们通常会把它放在循环中进行输出结果,有时候我们需要把这个 yield 产生的迭代器放在一个生成器函数中,也就是生成器嵌套。

下面例子:

def inner():
for i in range():
yield i
def outer():
g_inner=inner() #这是一个生成器
while True:
res = g_inner.send(None)
yield res g_outer=outer()
while True:
try:
print(g_outer.send(None))
except StopIteration:
break

这里有两篇写的很好的文章:

http://blog.theerrorlog.com/yield-from-in-python-3.html
http://stackoverflow.com/questions/9708902/in-practice-what-are-the-main-uses-for-the-new-yield-from-syntax-in-python-3

总结

  1、按照鸭子模型理论,生成器就是一种迭代器,可以使用for 循环进行迭代

  2、第一次执行 next(generator)时,会执行完yield 语句后程序进行挂起,所有的参数和状态进行保存

    再一次执行next(generator)时,会从挂起的状态开始往后执行

  在遇到程序结尾或者 StopIteration 时,循环结束

  3、可以通过 generator。send(arg) ;来传入参数,这是协程模型

  4、可以通过 generator。throw(exception)来传入一个异常,throw 语句会消耗掉一个 yield

    可以通过generator。close() 来手动关闭生成器

  5、next() 等价与send(None)

python 中的生成器(generator)的更多相关文章

  1. python中的生成器函数是如何工作的?

    以下内容基于python3.4 1. python中的普通函数是怎么运行的? 当一个python函数在执行时,它会在相应的python栈帧上运行,栈帧表示程序运行时函数调用栈中的某一帧.想要获得某个函 ...

  2. Python学习-39.Python中的生成器

    先回顾列表解释 lista = range(10) listb = [elem * elem for elem in lista] 那么listb就将会是0至9的二次方. 现在有这么一个需求,需要存储 ...

  3. python中的生成器(二)

    一. 剖析一下生成器对象 先看一个简单的例子,我们创建一个生成器函数,然后生成一个生成器对象 def gen(): print('start ..') for i in range(3): yield ...

  4. Day10 python高级特性-- 生成器 Generator

    列表生成式可以创建列表,但是受内存限制,列表容量时有限的,创建一个巨量元素的列表,不仅占用很大的存储空间,当仅仅访问前几个元素时,后面的绝大多数元素占用的空间都被浪费了. 如果list的元素可以按照算 ...

  5. python中的生成器(generator)总结

    1.实现generator的两种方式 python中的generator保存的是算法,真正需要计算出值的时候才会去往下计算出值.它是一种惰性计算(lazy evaluation). 要创建一个gene ...

  6. Python中的生成器与yield

    对于python中的yield有些疑惑,然后在StackOverflow上看到了一篇回答,所以搬运过来了,英文好的直接看原文吧. 可迭代对象 当你创建一个列表的时候,你可以一个接一个地读取其中的项.一 ...

  7. 深入理解Python中的生成器

    生成器(generator)概念 生成器不会把结果保存在一个系列中,而是保存生成器的状态,在每次进行迭代时返回一个值,直到遇到StopIteration异常结束. 生成器语法 生成器表达式: 通列表解 ...

  8. 聊聊Python中的生成器和迭代器

    Python中有两个重要的概念,生成器和迭代器,这里详细记录一下. 1. 生成器 什么是生成器呢? 通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而且,创建一个包 ...

  9. python中的生成器(一)

    我们先考虑一个场景: 有个情景需要循环输出1——10. 这里给两种方法: list1 = [1,2,3,4,5,6,7,8,9,10] for i in list1: print(i) for i i ...

  10. python学习之【第十三篇】:Python中的生成器

    1.为什么要有生成器? 在Python中,通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅 ...

随机推荐

  1. 安卓按键:读取txt开头出现未知字符的问题

    很多时候 我们读取txt 用traceprint输出后 最头上会莫名其妙多出一个问号 但是你用问号匹配他 却匹配不到  就是1个未知字符  这个到底是什么 怎么避免出现这个东西呢 这个主要是txt文件 ...

  2. Java 常见异常及处理方案

    Java 常见异常处理方案 异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的. 比如说,你的代码少了一个分号,那么运行出来结果是提示是错误java.lang.Error: ...

  3. Web基础了解版08-JSTL-Core标签库

    JSTL JSP为我们提供了可以自定义标签库(Tag Library)的功能,用来替代代码脚本,Sun公司又定义了一套通用的标签库名为JSTL(JSP Standard Tag Library),里面 ...

  4. makefile的书写

    工作中会遇到makefile的书写,有必要做一些笔记.尽管网上有”万能模板“可以使用,但我觉得还是有必要从最基础的写起. 平常在windows下开发,不知道自己用过makefile,其实大部分IDE里 ...

  5. C# 酒店管理系统知识点

    identity (m,n)自增 m开始n每次增加的值  默认(1,1) 列名  数据类型  约束  identity(m,n) 重新设置identity的值 1.语法 dbcc checkident ...

  6. Tensorflow2.0默认下载数据集到C盘的修改方法

    jupyter(Win版本)下载数据集会默认到C盘下,Linux会默认到root下,修改方式如下· tf1.x: import os import tensorflow as tftf.disable ...

  7. 队列的python实现

    队列(queue),是一种操作受限的线性表.只允许在队列的一端添加元素,在队列的另一端删除元素.能添加元素的一端称为队尾,能删除元素的一端称为队头. 队列最大的特性是:先进先出(FIFO,first ...

  8. 爬虫(十三):PIL模块

    1. PIL模块 在爬虫(十二):图形验证码的识别.滑动验证码的识别(B站滑动验证码)中我留下了一个悬念,为什么安装的是pillow模块,而不是PIL模块.这是因为PIL是python2的产物,它并没 ...

  9. 10.Redis的RDB和AOF两种持久化机制的优劣势对比

    1.RDB和AOF两种持久化机制的介绍 2.RDB持久化机制的优点3.RDB持久化机制的缺点4.AOF持久化机制的优点5.AOF持久化机制的缺点6.RDB和AOF到底该如何选择 我们已经知道对于一个企 ...

  10. Windows事件ID

    51 Windows 无法找到网络路径.请确认网络路径正确并且目标计算机不忙或已关闭.如果 Windows 仍然无法找到网络路径,请与网络管理员联系. 52 由于网络上有重名,没有连接.请到“控制面板 ...