生成器(generator)
1. 什么是生成器
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且, 创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后 面绝大多数元素占用的空间都白白浪费了。所以,如果列表元素可以按照某种算法推算出来,那我们是否 可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。
在 Python中,这种一边循环一边计算的机制,称为生成器:generator。
2. 创建生成器方法1
要创建一个生成器,有很多种方法。第一种方法很简单,只要把一个列表生成式的 [ ] 改成 ( )
#列表生成式(列表推导式)
l = [i for i in range(0,10,2)]
print(l)
# 生成器
g = (i for i in range(0,10,2))
print(g)
结果为:
[0, 2, 4, 6, 8]
<generator object <genexpr> at 0x00000000029B2BF8>
创建 L 和 G 的区别仅在于最外层的 [ ] 和 ( ) , L 是一个列表,而 G 是一个生成器。我们可以直接打印 出L的每一个元素,但我们怎么打印出G的每一个元素呢?如果要一个一个打印出来,可以通过 next() 函数 获得生成器的下一个返回值:
print(next(g)) # 0
print(next(g)) # 2
print(next(g)) # 4
print(next(g)) # 6
print(next(g)) # 8
print(next(g)) # StopIteration
生成器保存的是算法,每次调用 next(G) ,就计算出 G 的下一个元素的值,直到计算到最后一个元素, 没有更多的元素时,抛出 StopIteration 的异常。
可以使用 for循环取出每个元素,这样就不会报错,
for i in g: # g是一个生成器,可以直接循环
print(i)
结果为: 这样也不用担心会取不到值而报错
0
2
4
6
8
3.创建生成器方法2
generator非常强大。如果推算的算法比较复杂,用类似列表生成式的 for 循环无法实现的时候,还可以 用函数来实现。
比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加 得到: 1, 1, 2, 3, 5, 8, 13, 21, 34, ... 斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:
def fib(times):
a = 0
b = 1
n = 1
while n<=times:
print(b)
a,b = b,a+b
n+=1
fib(7)
结果为:
1
1
2
3
5
仔细观察,可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算 出后续任意的元素,这种逻辑其实非常类似generator。 也就是说,上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就 可以了:
#生成器写法
def fib(times):
a = 0
b = 1
n = 1
while n<=times:
#print(b)
yield b
a,b = b,a+b
n+=1
return "done!"
简单地讲,yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普 通函数,Python 解释器会将其视为一个 generator,调用 fab(5) 不会执行 fab 函数,而是返回一 个 iterable 对象!在 for 循环执行时,每次循环都会执行 fab 函数内部的代码,执行到 yield b 时,fab 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的 本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。 同样的,把函数改成generator后,我们基本上从来不会用 next() 来获取下一个返回值,而是直接使用 for 循环来迭代:
for i in F:
print(i) #结果与上面相同
但是用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值, 必须捕获StopIteration错误,返回值包含在StopIteration的value中:
while True:
try:
print(next(F))
except StopIteration as e:
print("生成器返回值:%s"%e.value)
break
总结:
生成器是这样一个函数,它记住上一次返回时在函数体中的位置。
对生成器函数的第二次(或第 n 次) 调用跳转至该函数中间,而上次调用的所有局部变量都保持不变。
生成器不仅“记住”了它数据状态;生成器还“记住”了它在流控制构造(在命令式编程中,这种构造不只 是数据值)中的位置。
生成器的特点:
1. 节约内存
2. 迭代到下一次的调用时,所使用的参数都是第一次所保留下的,即是说,在整个所有函数调用的参 数都是第一次所调用时保留的,而不是新创建的
生成器(generator)的更多相关文章
- Python复习之生成器 generator
生成器 generator def h(): print "hello" m = yield 5 print "m:", m d = yield 12 prin ...
- 生成器(generator)内部解析
#http://kb.cnblogs.com/page/87128/(未看完)
- 生成器generator
生成器generator 定义:一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator),如果函数中包含yield语法,那这个函数就会变成生成器 代码: def cash_out(a ...
- ES6中的迭代器(Iterator)和生成器(Generator)
前面的话 用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简 ...
- Hibernate中的主键生成器generator
本文讲述Hibernate的generator属性的意义.Generator属性有7种class,本文简略描述了这7种class的意义和用法. [xhtml] view plaincopy <c ...
- Python进阶内容(四)--- 迭代器(Iterator)与生成器(Generator)
迭代器 我们已经知道,可以直接作用于for循环的数据类型有以下几种: 一类是集合数据类型,如list.tuple.dict.set.str等: 一类是generator,包括生成器和带yield的ge ...
- 廖雪峰老师博客学习《通过生成器generator生成列表式杨辉三角》
说明:这是我接触生成器概念后,自己对它的理解,可能比较表面,没深入理解,也可能有错误.后续校正错误认知,将有关generator作为一个tag了! 希望以后能活用. 先贴出自己写的triangles( ...
- 003_生成器(generator)内部解析
#http://kb.cnblogs.com/page/87128/(未看完)
- Python之生成器(generator)和迭代器(Iterator)
generator 生成器generator:一边循环一边计算的机制. 生成器是一个特殊的程序,可以被用于控制循环的迭代行为.python中的生成器是迭代器的一种,使用yield返回值函数,每次调用y ...
- Python高级编程之生成器(Generator)与coroutine(二):coroutine介绍
原创作品,转载请注明出处:点我 上一篇文章Python高级编程之生成器(Generator)与coroutine(一):Generator中,我们介绍了什么是Generator,以及写了几个使用Gen ...
随机推荐
- pyspark 逻辑回归程序
http://www.qqcourse.com/forum.php?mod=viewthread&tid=3688 [很重要]:http://spark.apache.org/docs/lat ...
- py3 读入和写入csv,txt文件
import numpy as npimport pandas as pdimport time import datetimeimport csv http://pandas.pydata.org/ ...
- ERROR Couldn't find hvm kernel for Ubuntu tree.
安装python-virtinst git clone https://github.com/palli/python-virtinst.gitcd python-virtinstpython set ...
- tomcat支持 https
首先 安装nginx ,在nginx.conf 中引入 include /app/conf/nginx/vhosts/*.conf; 配置 并在conf/vhosts 目录 中配置virtual.c ...
- javaService
JavaService.exe -install TestService "%JAVA_HOME%\jre\bin\server\jvm.dll" -Djava.class.pat ...
- Spring之jdbcTemplate实现orm
public List<AppUser> getAppUser(AppUser appUser) { String sql = "select * from appuser a ...
- BP神经网络学习
人工神经元模型 S型函数(Sigmoid) 双极S型函数 神经网络可以分为哪些? 按照连接方式,可以分为:前向神经网络 vs. 反馈(递归)神经网络 按照学习方式,可以分为:有导师学习神经网络 ...
- codeforces 722D Generating Sets 【优先队列】
You are given a set Y of n distinct positive integers y1, y2, ..., yn. Set X of n distinct positive ...
- ffmpeg编码中的二阻塞一延迟
1. avformat_find_stream_info接口延迟 不论是减少预读的数据量,还是设置flag不写缓存,我这边都不实用,前者有风险,后者会丢帧,可能我还没找到好姿势,记录在此,参考:htt ...
- .net 报错access to the path c:\tempimagefiles\msc_cntr_0.txt is denied
报错信息: 解决方法: 在 Web.Config 的 <System.Web> 里加 <identity impersonate="true"/> 节点即可 ...