在Python中,一边循环一边计算的机制,称为生成器:generator。生成器不必创建完整的list,可以在循环中不断推算出后续的元素,从而可以在获取所需元素的同时节省存储空间。
创建generator即把列表生成式的[]
改成()
。
>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x1022ef630>
一般通过for循环
来获取generator的元素,也可以使用next(g)
来获取下一个元素。
>>> g = (x * x for x in range(10))
#通过for循环获取元素
>>> for n in g:
... print(n)
...
0
1
4
#通过next()获取元素
>>> next(g)
0
>>> next(g)
1
通过yield
关键字将一个函数变成generator
。例如:
函数的定义:
def fib(max):
n, a, b = 0, 0, 1
while n < max:
print(b)
a, b = b, a + b
n = n + 1
return 'done'
生成器的定义:
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'
两者的差别在于生成器将函数的print(b)
改为yield b
。yield
可以翻译为生成
,即基于某次计算生成某个元素,而不是提前存储了该元素。
函数式的generator
一般采用for
循环来获取元素,也可以通过next()
来获取下一个元素的值,例如:
>>> for n in fib(6):
... print(n)
...
1
1
2
3
5
8
如果要获取return
的内容,可以捕获StopIteration
错误,返回值包含在StopIteration
的value
中。
>>> g = fib(6)
>>> while True:
... try:
... x = next(g)
... print('g:', x)
... except StopIteration as e:
... print('Generator return value:', e.value)
... break
...
g: 1
g: 1
g: 2
g: 3
g: 5
g: 8
Generator return value: done
参考: