带有yield关键字的函数被称为生成器(generator)。
生成器的适用场景如下:
- 列表元素可以按照某种算法推算出来,用数学的话讲就是——已知数列的通项公式或递推公式。
- 列表元素数量庞大,可能有上百万个,甚至无穷个。
- 仅仅需要访问列表中前几个元素,后面绝大多数元素占用的空间都是一种浪费。
先举个简单的例子。
ls = [2*x for x in range(1,11)] # 列表
ge = (2*x for x in range(1,11)) # 生成器
print(ls)
print(ge)
输出:
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
<generator object <genexpr> at 0x0000025E58529048>
可见,只要在列表生成式外括上圆括号,就创建了一个生成器。
再举个例子:斐波那契数列。
# 普通斐波那契数列代码
def fib1(n):
a,b = 0,1
for i in range(n):
print(b,end = ' ')
a,b = b,a+b
# 生成器斐波那契数列代码
def fib2(n):
a,b = 0,1
for i in range(n):
yield b
a,b = b,a+b
可见,想把一个函数变成生成器,只要把print()改为yield就可以了。
如果列表元素可以按照某种算法推算出来,那么可以在循环的过程中不断推出后续的元素,这样就不必创建完整的list,从而节省大量的空间。
生成器函数的执行过程可以做一下了解,一般不会故意搞得这么麻烦(的吧?):在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处往下继续执行。
# 生成器函数的执行过程
def test_yield():
print("step 1")
yield 1
print("step 2")
yield 2
print("step 3")
yield 3
print("step 4")
t1 = test_yield()
参考资料:
https://www.liaoxuefeng.com/wiki/1016959663602400/1017318207388128