迭代器和生成器是python中两个非常强大的特性,生成器是一种特殊的迭代器,编写程序时你可以不使用生成器达到同样的效果,但是生成器让你的程序更加pythonic。
什么是生成器(generator)
生成器不会把结果保存在一个结果中,而是保存函数的执行状态,在每次进行迭代时返回一个值,直到遇到StopIteration异常结束。
为什么有了迭代器还需要生成器?
- 1、存在即合理,生成器使得python更为简洁。
- 2、生成器使得python模仿协同程序的概念得以实现,所谓协同程序,就是可以独立运行的函数的调用,函数可以暂停或者挂起,并在需要的时候从程序离开的地方继续或者重新开始 创建生成器非常简单,只要在函数中加入yield语句即可。
- 3、迭代器需要我们自己去定义一个类和实现相关的方法,而生成器并不涉及魔法方法,甚至巧妙的避开的类和对象,仅仅通过普通的函数就可以实现了。
生成器自动实现了“迭代器协议”(即__iter__和__next__方法),不需要再手动实现两方法。
生成器语法
1、生成器表达式:
如果我们接触过列表表达式,一定会被这种简洁优美的语法所折服,而生成器表达式只不过把列表解析的 [] 换成 () ,返回的结果就是生成器对象。
生成器表达式能做的事情列表解析基本都能处理,只不过在需要处理的序列数据量比较大时,列表解析比较费内存,这个时候生成器的惰性计算就显示出威力了。
>>> gener = (x**2 for x in range(5))
>>> gener
<generator object at 0x0000000002FB7B40>
>>> for g in gener:
... print(g, end='-')
0-1-4-9-16-
2、生成器函数
在函数中如果出现了yield关键字,那么该函数就不再是普通函数,而是生成器函数。yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator。
对于普通函数,一般结束以return语句、或者异常,或者所有语句执行完毕。一旦函数将控制权交还给调用者,就意味着函数中所作 的工作已经保存在局部变量(函数中定义的变量)中的数据全部丢失,再次调用这个函数时,将从头创建执行。
对于生成器,函数中每次使用yield产生一个值,函数就返回该值,然后停止执行,等待被激活,被激活后继续在原来的位置执行。也就是说,生成器可以暂时挂起函数,并保留函数的局部变量等数据,再次调用的时候,从上次暂停的位置继续执行下去。
举个栗子:斐波那契数列
def fib(): #无限循环
a,b = 0,1
while 1:
a,b = b,a+b
yield a
for i in fib():
if i > 100: #退出循环的条件
break
print(i)