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)) # 0print(next(g)) # 2print(next(g)) # 4print(next(g)) # 6print(next(g)) # 8print(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 = 0b = 1n = 1while n<=times:print(b)a,b = b,a+bn+=1
fib(7)

结果为:

1
1
2
3
5

仔细观察,可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算 出后续任意的元素,这种逻辑其实非常类似generator。 也就是说,上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就 可以了:

#生成器写法
def fib(times):a = 0b = 1n = 1while n<=times:#print(b)yield ba,b = b,a+bn+=1return "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. 迭代到下一次的调用时,所使用的参数都是第一次所保留下的,即是说,在整个所有函数调用的参 数都是第一次所调用时保留的,而不是新创建的

转载于:https://www.cnblogs.com/mswei/p/9283386.html

生成器(generator)相关推荐

  1. 生成器generator

    生成器generator 定义:一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator),如果函数中包含yield语法,那这个函数就会变成生成器 代码: def cash_out(a ...

  2. python3.x中的生成器generator调用next方法

    python3.x中的生成器generator调用next方法 标签: 编辑 删除 今天写了一段Python程序,用到了Python的generator.当我用到generator的next方法时,s ...

  3. python生成斐波那契_python学习-生成器(generator)及斐波那契;yield

    生成器(generator):生成器不同于列表,是根据某一种算法来推算,在循环过程中不断计算出后续的元素,从而节省大量空间. generator的创建方式有很多种. 第一种和列表创建方式相类似,只要将 ...

  4. python之路day14--列表生成式、生成器generator、生成器并行

    列表生成式 列表生成式阅读量: 44 现在有个需求,现有列表a=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],要求你把列表里的每个值加1,你怎么实现?你可能会想到2种方式 二逼青年版 ...

  5. python生成器函数(generator),python3学习笔记:生成器generator

    简单了解下生成器generator,主要是yield的返回值和send的传参,记录下. 生成器的基本属性 generator = 函数 + yield 简单说,就是一个函数,里面用到了关键字yield ...

  6. Python_生成器Generator

    简介 生成器是用来创建Python序列的一个对象,可以用它迭代庞大的序列而不需在内存中创建和存储整个序列,因为它仅仅保存了这个序列的推算算法.Python3中range()是标准的一个生成器 主要作用 ...

  7. Python组合数据类型:容器类型总览,(不)可变数据类型immutable、(不)可迭代对象iterable、迭代器iterator、生成器generator、语法糖

    一.组合数据类型container objects 组合数据类型container objects:能够表示多个数据的类型 集合类型:集合类型是一个元素集合,元素无序不重不变 序列类型:序列类型是一个 ...

  8. php generator 风雪,PHP 生成器Generator理解

    这篇文章介绍的内容是关于PHP 生成器Generator理解,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 转载整理自:寄凡.风雪之隅.PHP手册 生成器(Generator)可解决的 ...

  9. ES6中的迭代器(Iterator)和生成器(Generator)

    用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简化数据操作 ...

  10. 深入解析ES6中的迭代器(Iterator)和生成器(Generator)

    用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简化数据操作 ...

最新文章

  1. 自动驾驶中高效的激光雷达里程计
  2. MVP谈WinHEC:Demo很炫 Windows 7启动快
  3. 每日一皮:你偷偷藏私房钱时被老婆发现的样子...
  4. android gradle is插件,android gradle 插件创建 configuration
  5. 【数据竞赛】Kaggle秘技,用Sigmoid函数做回归问题!
  6. WCF消息之XmlDictionaryWriter
  7. Cognos TM1_10.1.1服务端配置
  8. 从笑话中看到产品创意
  9. java提高篇四_(转)java提高篇(四)-----理解java的三大特性之多态
  10. python下雨动画特效_pygame用blit()实现动画效果
  11. JellyViewPager
  12. 自己封装的一个模拟下拉列表的插件
  13. Netty4.0学习笔记系列之五:自定义通讯协议
  14. mysql+enable+sql+log_MySQL -- redolog + binlog
  15. win10添加uefi linux引导,win10 ubuntu双系统:UEFI GPT和Legacy MBR引导模式
  16. iTunes驱动程序缺少用于导入和刻录CD与DVD的注册设置
  17. [原创]C#中国象棋网络版源代码-C# Chinese Chess Source Code
  18. pandas中merge函数的用法
  19. 为网站配置免费的HTTPS证书 3-4
  20. Qt将选中的字体加粗下划线

热门文章

  1. 带女朋友回家家里人一共给了她3500我拿走了真的有错吗?
  2. 老年人用什么方式存款最好?
  3. 网店如何提高顾客的回购率?
  4. 企业创新流程的“正向推”与“反向推”思考
  5. 作为一位75后的职场宝妈
  6. 2K分辨率下1070TI更换2080S能有多大提升,值得换吗?
  7. TCP快速重传为什么是三次冗余ack
  8. 虚电路网络和数据报网络
  9. 进程互斥的软件实现方法
  10. sql组合键设置外键_学习SQL:外键