生成器(generator) 详解
1. 生成器是什么?
>>>[i for i in range(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
示例代码如下:
>>>[x**2 for x in [1,2,5,8,7] if x>5]
[64, 49]
3. 创建生成器方法1
>>>obj = (i for i in range(5))
>>>obj
<generator object <genexpr> at 0x03F79D80>
>>>next(obj)
0
>>>next(obj)
1
>>>obj.__next__()
2
>>>obj.__next__()
3
>>>obj.__next__()
4
注意:generator保存的是算法,每次调用next()方法,就计算出generator的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。因为generator也是可迭代对象,所以可以使用for循环来取出数据。
>>> list = (x *2 for x in range(5))
>>> for num in list:
... print(num)
...
0
2
4
6
8
4. 创建生成器方法2
生成器函数: 在函数中如果出现了yield关键字,那么该函数就不再是普通函数,而是生成器函数。
但是生成器函数可以生产一个无限的序列,这样列表根本没有办法进行处理。yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator。generator非常强大。如果推算的算法比较复杂,用类似列表生成式的 for 循环无法实现的时候,还可以用函数来实现。
In [30]: def fib(n):
....: current = 0
....: num1, num2 = 0, 1
....: while current < n:
....: num = num1
....: nm1, num2 = num2, num1+num2
....: current += 1
....: yield num
....: return 'done'
....:
In [31]: F = fib(5) In [32]: next(F)
Out[32]: 0 In [33]: next(F)
Out[33]: 1 In [34]: next(F)
Out[34]: 1 In [35]: next(F)
Out[35]: 2 In [36]: next(F)
Out[36]: 3 In [37]: next(F)
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-37-8c2b02b436bn> in <module>()
----> 1 next(F) StopIteration: done
5. yield 与 return
5.1 在一个生成器中,如果没有return,则默认执行到函数完毕时返回StopIteration;
>>> def g1():
... yield 6
...
>>> g=g1()
>>> next(g) #第一次调用next(g)时,会在执行完yield语句后挂起,所以此时程序并没有执行结束。
6
>>> next(g) #程序试图从yield语句的下一条语句开始执行,发现已经到了结尾,所以抛出StopIteration异常。
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
5.2 如果在return后返回一个值,那么这个值为StopIteration异常的说明,不是程序的返回值。
>>> def g2():
... yield 'hello'
... return 'error information'
...
>>> g=g2()
>>> next(g)
'hello'
>>> next(g)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration: error information
5.3 如果遇到return,如果在执行过程中 return,则直接抛出 StopIteration 终止迭代。
>>> def g3():
... yield 'a'
... return
... yield 'b'
...
>>> g=g3()
>>> next(g) #程序停留在执行完yield 'a'语句后的位置。
'a'
>>> next(g) #执行到此处,程序发现下一条语句是return,所以抛出StopIteration异常,这样yield 'b'语句永远也不会执行。
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
5.4 close()函数 手动关闭生成器函数,后面的调用会直接返回StopIteration异常。
>>> def g4():
... yield 1
... yield 2
... yield 3
...
>>> g=g4()
>>> next(g)
1
>>> g.close()
>>> next(g) #关闭后,yield2 和yield3 语句将不再起作用
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
In [35]: def gen():
....: i = 0
....: while i<5:
....: temp = yield i
....: print(temp)
....: i+=1
....: In [43]: f = gen() In [44]: next(f)
Out[44]: 0 In [45]: f.send('haha')
haha
Out[45]: 1 In [46]: next(f)
None
Out[46]: 2 In [47]: f.send('haha')
haha
Out[47]: 3
上方代码执行到yield时,gen函数作用暂时保存,返回 i 的值; temp接收下次f.send("haha"),即send发送过来的值,next(f)等价f.send(None)
总结
- 使用了yield关键字的函数不再是函数,而是生成器。(使用了yield的函数就是生成器)
- 可作用于
for循环的对象都是Iterable类型; - next(f) 等价于 f.send(None)
- yield关键字有两点作用:
- 保存当前运行状态(断点),然后暂停执行,即将生成器(函数)挂起
- 将yield关键字后面表达式的值作为返回值返回,此时可以理解为起到了return的作用
- 可以使用next()函数让生成器从断点处继续执行,即唤醒生成器(函数)
生成器(generator) 详解的更多相关文章
- MyBatis Generator 详解
MyBatis Generator中文文档 MyBatis Generator中文文档地址:http://mbg.cndocs.tk/ 该中文文档由于尽可能和原文内容一致,所以有些地方如果不熟悉,看中 ...
- MyBatis Generator 详解 【转来纯为备忘】
版权声明:版权归博主所有,转载请带上本文链接!联系方式:abel533@gmail.com 目录(?)[+] MyBatis Generator中文文档 运行MyBatis Generator X ...
- MyBatis Generator 详解(转)
MyBatis Generator中文文档 MyBatis Generator中文文档地址:http://mbg.cndocs.tk/ 该中文文档由于尽可能和原文内容一致,所以有些地方如果不熟悉,看中 ...
- MyBatis Generator 详解 专题
idea中有plugin可提高效率: http://www.henryxi.com/use-idea-mybatis-plugin-generate-mapper-files eg: <?xml ...
- ES6新特性三: Generator(生成器)函数详解
本文实例讲述了ES6新特性三: Generator(生成器)函数.分享给大家供大家参考,具体如下: 1. 简介 ① 理解:可以把它理解成一个函数的内部状态的遍历器,每调用一次,函数的内部状态发生一次改 ...
- python yield generator 详解
本文将由浅入深详细介绍yield以及generator,包括以下内容:什么generator,生成generator的方法,generator的特点,generator基础及高级应用场景,genera ...
- 面向对象设计模式_生成器模式详解(Builder Pattern)
首先提出一个很容易想到应用场景: 手机的生产过程:手机有非常多的子件(部件),成千上万,不同品牌的手机的生产过程都是复杂而有所区别的,相同品牌的手机在设计上也因客户需求多样化,大到型号,小到颜色,是否 ...
- generator详解
generator函数 yield可以返回值,也可以传入值 形式: 注意!generator不能写成arrow function的形式!!! function *函数(){ 代码1... let a ...
- (转)Python中的generator详解
本文转自:http://www.cnblogs.com/xybaby/p/6322376.html 作者:xybaby 注:本文在原文基础上做了一点点修改,仅仅作为个人理解与记忆,建议直接查看原文. ...
随机推荐
- leetcode548 Split Array with Equal Sum
思路: 使用哈希表降低复杂度.具体来说: 枚举j: 枚举i,如果sum[i - 1] == sum[j - 1] - sum[i],就用哈希表把sum[i - 1]记录下来: 枚举k,如果sum[k ...
- poj1947(树上分组背包)
题目链接:https://vjudge.net/problem/POJ-1947 题意:给定一棵树,求得到一个结点数为p最少删多少条边. 思路: 明显的树形dp,分组背包.用dp[u][j]表示在结点 ...
- Spring4学习回顾之路11-AOP
Srping的核心除了之前讲到的IOC/DI之外,还有一个AOP(Aspect Oriented Programming:面向切面编程):通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术 ...
- Python可修改和不可修改类型变量(mutuable and immutuable)
通俗的讲,可修改可以理解为可以在数据所在内存地址直接修改,而不可修改则意味着一旦修改便是创建新的数据对象,而不是在原来的对象内存地址修改 1,Mutuable object [sourcecode l ...
- gitlab LFS 的应用实践
今天看到的gitlab LFS的文档,将自己的理解整理成博客,加深自己的印象.具体gitlab LFS的介绍可以直接百度了,不在这里详细阐述.只提一下他的作用:LFS就是Large File Stor ...
- (转)如何真正实现由文档驱动的API设计?
前言 本文主要介绍了一种新的开发思路:通过反转开发顺序,直接从API文档中阅读代码.作者认为通过这种开发方式,你可以更清楚地知道文档表达出什么以及它应该如何实现. 如果单从API文档出发,由于信息量不 ...
- 怎样监听HTTP请求的成功、失败与进行时
1. 监听请求成功: xhr.onload 2. 监听请求失败: xhr.onerror 3. 监听请求数据下载中: xhr.onprogress xhr.onload = function() { ...
- MQTT图形化客户端比较
1 MQTT.fx (1)协议支持 TCP(tcp) TLS(tls) (2)特点 界面美观,操作便捷 不支持WebSocket协议 基于java开发 支持代理 通过Nashorn Engine的JS ...
- java大框架
本文章,列出了一些程序员需要学习的技术和知识点,有些技术和知识点没有写道,欢迎大家进行修改和补充,有些技术公司用到,大家需要先学习,有些技术和知识点过时,大家可以了解.本人笔记连接[[http://2 ...
- Oracle cmd 命令
1.登陆 输入sqlplus,回车.然后输入用户名和密码. 退出exit. 2.查看服务 Window打开服务的cmd命令 windows +R :services.msc---本地服务设置 rege ...