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

浏览: 4240

前言

进阶部分连载继续~

如果还没看过我的入门连载部分,先看:

https://ask.hellobi.com/blog/wangdawei/10288


当然,小编的免费入门课程已经有咯,看过连载的朋友可以看看视频再快速梳理一遍~

视频传送门:https://edu.hellobi.com/course/234

图片.png

前文传送门:

Python进阶系列连载(1)——那些容易被忽略的问题(上)

Python进阶系列连载(2)——那些容易被忽略的问题(中)

Python进阶系列连载(3)——那些容易被忽略的问题(下)

Python进阶系列连载(4)——迭代器


生成器


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


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


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

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


见过这种东西吧:


图片.png


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

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


简单方法创建生成器


我们看个例子:


图片.png


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


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


图片.png


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

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


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

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


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


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


图片.png


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


函数进化为生成器


还记得函数的定义么?


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

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


图片.png


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

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

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

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

所以我们对其进行修改:


图片.png


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


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


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


图片.png


我们把函数中的return换成yield

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

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


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


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

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


仔细看好:


图片.png


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

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

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

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


图片.png


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

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


图片.png


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


总结

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

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

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

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

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

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


今天作业:

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

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

下课

人生苦短,我选Python

未完待续,连载中......

欢迎评论指出文中错误和提问~~~


下一篇链接:Python进阶系列连载(6)——生成器(中)

推荐 11
本文由 ID王大伟 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

2 个评论

非常好,感谢分享~
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-161-15841f3f11d4> in <module>()
----> 1 next(a)

<ipython-input-157-88e0d66701dd> in Fib()
4 for i in range(2):
5 a,b=b,a+b
----> 6 print('即将开始第'+str(i+1)+'次yield')
7 yield b
8 print('第'+str(i+1)+'次yield结束')

TypeError: 'tuple' object is not callable


老师为什么每次都报这个错误呢,我没找到原因,谢谢老师了。

要回复文章请先登录注册