Python进阶系列连载(5)——生成器(上)

作者:王大伟

Python爱好者社区唯一小编

博客:https://ask.hellobi.com/blog/wangdawei

生成器

还记得在迭代器里我们说为什么将列表转为迭代器么?

小明:因为列表太大的话占用内存太大,做成迭代器可以节省空间,用的时候再拿出部分

是的,今天要讲的生成器是不会把结果保存在一个系列中,而是保存生成器的状态。

在每次进行迭代时返回一个值,直到遇到StopIteration异常结束。

见过这种东西吧:

你可以认为每一杯饮料就是一个生成的对象,我不会一次倒出所有的饮料

而是要喝的时候去倒出一杯(也就是需要的时候生成一个)

简单方法创建生成器

我们看个例子:

我们发现,当要生成的list非常大时,抛出异常,存储报错。

那怎样生成这种巨大的list呢?

你亲手试一下,发现瞬间程序就运行结束了

我们看到,b是一个generator,也就是生成器模式

你应该已经注意到,生成器的创建很简单,将列表生成式的中括号改成小括号即可

注意:这里说的不是列表,因为列表的中括号改成小括号是元组!

那我们怎么生成一个内容呢?

和之前的迭代器相同,使用next()函数即可:

直到最后会抛出异常,也就是到达了生成器的末端了

函数进化为生成器

还记得函数的定义么?

我们在之前用递归定义了一个斐波那契数列

现在我们定义一个新的函数来生成斐波那契数列的第n项

为了实现后一项等于前两项之和使用了a,b = b,a+b

为什么这样写,留给大家思考~

提示:可以输入n=3,自己感受一下调用函数过程中a和b的变化

值得注意的是,这个函数,当n=0时返回的是1,而不是正确的0

所以我们对其进行修改:

在循环之前,加了一个判断

小明:老湿!你这个说的还是函数啊,和生成器有啥关系?说好的函数进化成生成器呢?

好的,我们看看函数怎么进化为生成器!

我们把函数中的return换成yield

函数就进化成了生成器,当我们调用时,发现返回的是生成器对象

为了拿到数据,我们应该怎么做呢?

小红:老师,是不是可以试试next()函数呢?

对,不过在此之前,我们先要用一个变量去接收这个生成器对象

并且为了观察生成器的特点,我们对函数进行修改!

仔细看好:

当我们使用next(a)对生成器操作一次时,会返回循环一次的值

也就是在yield处结束本次运行

但它的特点就是下次使用next(a)时,接着上次的断点继续运行,直到下一个yield

不断使用next(a),直到运行到生成器结尾处,如下图:

可能你对他的运行过程还不是特别清晰

我们加上print输出来彻底搞懂他的运行过程:

发现每次返回值都是在yield的地方了吧~

总结

0.讲了两种生成器创建方式

1.加了yield的函数就变成了生成器

2.要定义一个变量接收生成器的返回值

3.使用next()获取生成器每次返回的值,并且断点在yield处

4.下次使用next()从上次的断电往下执行,直到生成器末端(这里表现为循环结束)

5.生成器属于迭代器,所以肯定是可迭代对象啦~

今天作业:

敲一遍代码,理解一下两种生成器创建方式

自己不敲代码永远学不会写代码

本文来自企鹅号 - Python爱好者社区媒体

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏liulun

Nim教程【二】

第一篇教程1秒内就被管理员从首页踢掉了 管理员嫌内容太少,没有含金量,这次多写一些。 这应该是国内第一个关于Nim入门的系列教程 好,闲话休提,言归...

273100
来自专栏数据科学与人工智能

【Python环境】Python面试题汇总(一)

拿网络上关于Python的面试题汇总了,给出了自认为合理的答案,有些题目不错,可以从中学到点什么,答案如不妥,请指正...... +++++++++++++++...

37360
来自专栏锦小年的博客

python学习笔记6.6-类的惰性属性

我们想将一个只读属性定义为property属性方法,只有在访问它时才参与计算。同时,一旦访问了该属性,希望把计算出来的值缓存起来,不要每次访问它时都要重新计算。...

228100
来自专栏nnngu

经典Java面试题收集

2、访问修饰符public,private,protected,以及不写(默认)时的区别?

42280
来自专栏从流域到海域

《笨办法学Python》 第18课手记

《笨办法学Python》 第18课手记 本节课将创建函数,跟C语言里面的的定义函数差不多。 作者在每个函数开头都加了解释该函数功能的英文注释。为了方便理解,我将...

21480
来自专栏尾尾部落

[剑指offer] 旋转数组的最小数字

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为...

10520
来自专栏Java爬坑系列

【Java入门提高篇】Day17 Java异常处理(下)

15130
来自专栏影子

jsp的C标签一般使用方法以及js接收servlet中的对象及对象数字

26140
来自专栏小鹏的专栏

tf API 研读3:Building Graphs

tensorflow是通过计算图的方式建立网络。 比喻说明: 结构:计算图建立的只是一个网络框架。编程时框架中不会出现任何的实际值,所有权重(weight)和偏...

27170
来自专栏风口上的猪的文章

.NET面试题系列[10] - IEnumerable的派生类

IEnumerable分为两个版本:泛型的和非泛型的。IEnumerable只有一个方法GetEnumerator。如果你只需要数据而不打算修改它,不打算为集合...

13720

扫码关注云+社区

领取腾讯云代金券