生成器

Posted lifeasdog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了生成器相关的知识,希望对你有一定的参考价值。

概念辨析

生成器其实就是一种特殊的迭代器。它使一种更为高级、更为优雅的迭代器。

仅仅在迭代至某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。

这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件,或是斐波那契数列等等。这个特点被称为延迟计算或惰性求值(Lazy evaluation)。

生成器主要的特点就是:延迟操作,在需要的时候产生结果,而不是立即产生结果。

列表生成器

#先写一个列表a,可以随意取数据
a = [1,2,3,4,5]
print(a[0])
#打印1
#再生成一个列表,也可以随意取数据
b = [i+1 for i in range(5)]
print(b[3])
#打印3
#再生成一个生成器列表,无法随意取数据了
c =(i+1 for i in range(5))
print(c(3))
#打印 生成器c is not callble
#不能随意访问任意值。只能依次取

上面例子中的列表c被称为列表生成式,思考一下,这个式子很像我之前自己写的迭代器,都是通过一种算法来实现一串数据的生成,遗憾的是列表生成器中的算法是固定的:for语句控制下有限的几种变化。

是不是可以还是像写迭代器一样,把算法灵活化、开放化?同时保留列表生成器延迟这个特性?

这就诞生了生成器函数的需求。

那么要如何写一个生成器函数?

同时,留意到在定义上其实生成器是迭代器的子集,即生成器具有_iter_()和_next_()方法,那么在构想生成器的类时,不用再重复写这两个功能,只需要在_next_()中写明算法;再加上一个类似于可以随时暂停的功能——

yield,就是这个功能。yield如果出现在一个函数中,相当于为这个函数增添了三个功能:_iter_()和_next_()方法,以及挂起功能。即拥有yield的函数就是一个生成器——注意,生成器是拥有yield的函数的返回值,而不是这个函数自己。

(我认为语法糖就是一个打包的意思,把一堆功能浓缩为一个符号)

综上,一个生成器函数就写成了。

一个思考不知道对不对

在写一个迭代器的时候,会随着迭代器的调用迭代出所有值,加入有一万个值,就会非常浪费内存和时间。于是想,能不能有一种机制,把某一个值保存起来,需要时再用。

保存在哪儿?生成器中。把这种包含了迭代器功能同时还能保存值得,叫做生成器。

生成器

生成器函数的返回值,就是生成器。

先抄一些生成器的干货:

1.生成器的唯一注意事项就是:生成器只能遍历一次。

2.使用生成器以后,代码行数更少。——不看过程,只看结果

3.生成器表达式能做的事情列表解析基本都能处理,只不过在需要处理的序列比较大时,列表解析比较费内存。生成器可以通过延迟来减少内存占用和计算速度。

4.yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator。

5.每次循环都会执函数内部的代码,执行到 yield语句 时, 函数就返回一个迭代值,下次迭代时,代码从 yield的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。

6.yield就是暂停/挂起的作用。生成器不会把结果保存在一个系列中,而是保存生成器的状态,在每次进行迭代时(调用next)返回一个值,直到遇到StopIteration异常结束。

 

以上是关于生成器的主要内容,如果未能解决你的问题,请参考以下文章

Apollo Codegen 没有找到生成代码的操作或片段

前端开发工具vscode如何快速生成代码片段

前端开发工具vscode如何快速生成代码片段

vscode代码片段生成vue模板

VS Code配置snippets代码片段快速生成html模板,提高前端编写效率

vs 2010代码片段