生成器的概念
生成器是一个函数,它会记住每一次调用的数据状态和在流控制构造中的位置。在下一次调用时,所有参数都是第一次调用时所保留的,而不是新创建的。
列表生成式
作为对比,先来介绍一下列表生成式List Comprehensions。
生成一个0-9的列表:
#方式一:
a=list(range(10))
print(a)
结果:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
#方式二:
b=[x for x in range(10)]
print(b)
结果:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
加入条件判断的列表生成式:
def f(n):
return n*n
c=[f(x) for x in range(10) if x%2==0]
print(c)
结果:
[0, 4, 16, 36, 64]
多参数的列表生成式:
d={'Bob':18,'Allice':20,'Cinda':17}
for m,n in d.items():
print(m,"'s age=",n)
结果:
Allice 's age= 20
Bob 's age= 18
Cinda 's age= 17
小结:
使用列表生成式可以用很简洁的代码快速生成List,但是当列表元素特别巨大或者无限的时候,使用就会占用过多内存甚至报错。
生成器
生成器generator就能克服列表生成器存在的一些不足,它不必一次性创建完整的List,而是在循环的过程中不断推算后续的元素,一边循环一边计算。
定义方式:
1.将列表生成器的[]改为()就创建了一个generator。
s=(x for x in range(10))
print(s)
print(next(s))#等价于s.__next__()
print(next(s))
print(next(s))
print(next(s))
for i in s:
print(i)
输出结果:
<generator object <genexpr> at 0x00000216FEA3C048>
0
1
2
3
4
5
6
7
8
9
因为生成器能记录状态,所以在运行for循环代码的时候它不是从头开始计算,而是从当前状态开始往后循环。
2.使用yield。
如果一个函数的定义里面含有yield关键字,那么这个函数就不再是一个普通函数,而是一个generator。
- 函数一般会顺序执行,遇到return等语句或者执行到最后一行函数语句就会返回。
- 区别于一般函数,generator在每次调用next()的时候,生成器函数运行到yield之处,返回yield后面的值且在这个地方暂停,所有的状态都会被保持住,直到下次next函数被调用,或者碰到异常循环退出
def pir():
print('first')
yield "a"
print('second')
yield "b"
print('last')
yield "c"
输出结果:
first
second
b
last
c