1. 生成器的介绍
根据程序员制定的规则循环生成数据,当条件不成立时则生成数据结束。数据不是一次性全部生成处理,而是使用一个,再生成一个,可以节约大量的内存。
2. 创建生成器的方式
- 生成器推导式
- yield 关键字
生成器推导式:
- 与列表推导式类似,只不过生成器推导式使用小括号
# 创建生成器
my_generator = (i * 2 for i in range(5))
print(my_generator)
# next获取生成器下一个值
# value = next(my_generator)
# print(value)
# 遍历生成器
for value in my_generator:
print(value)
代码说明:
- next 函数获取生成器中的下一个值
- for 循环遍历生成器中的每一个值
运行结果:
<generator object <genexpr> at 0x101367048>
0
2
4
6
8
yield 关键字:
- 只要在def函数里面看到有 yield 关键字那么就是生成器
def mygenerater(n):
for i in range(n):
print('开始生成...')
yield i
print('完成一次...')
if __name__ == '__main__':
g = mygenerater(2)
# 获取生成器中下一个值
# result = next(g)
# print(result)
# while True:
# try:
# result = next(g)
# print(result)
# except StopIteration as e:
# break
# # for遍历生成器, for 循环内部自动处理了停止迭代异常,使用起来更加方便
for i in g:
print(i)
代码说明:
- 代码执行到 yield 会暂停,然后把结果返回出去,下次启动生成器会在暂停的位置继续往下执行
- 生成器如果把数据生成完成,再次获取生成器中的下一个数据会抛出一个StopIteration 异常,表示停止迭代异常
- while 循环内部没有处理异常操作,需要手动添加处理异常操作
- for 循环内部自动处理了停止迭代异常,使用起来更加方便,推荐大家使用。
运行结果:
开始生成...
0
完成一次...
开始生成...
1
完成一次...
3. 生成器的使用场景
数学中有个著名的斐波拉契数列(Fibonacci),数列中第一个数为0,第二个数为1,其后的每一个数都可由前两个数相加得到:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...
现在我们使用生成器来实现这个斐波那契数列,每次取值都通过算法来生成下一个数据, 生成器每次调用只生成一个数据,可以节省大量的内存。
def fibonacci(num):
a = 0
b = 1
# 记录生成fibonacci数字的下标
current_index = 0
while current_index < num:
result = a
a, b = b, a + b
current_index += 1
# 代码执行到yield会暂停,然后把结果返回出去,下次启动生成器会在暂停的位置继续往下执行
yield result
fib = fibonacci(5)
# 遍历生成的数据
for value in fib:
print(value)
运行结果:
0
1
1
2
3
4. 小结
- 生成器是根据算法生成数据的一种机制,每次调用生成器只生成一个值,可以节省大量内存。
- 生成器的创建有两种方式:
- 生成器推导式
- yield 关键字