一、生成器定义
通过列表生成表达式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
1 >>> l = [x * x for x in range(10)] 2 >>> l 3 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] 4 >>> g = (x * x for x in range(10)) 5 >>> g 6 <generator object <genexpr> at 0x1013e0780>
二、表达式生成器
创建l和g的区别仅在于最外层的[]和(),l是一个list,而g是一个generator。可以直接打印出l的每一个元素,打印出g的每一个元素需要使用next()函数。
1 >>> g = (x * x for x in range(10)) 2 >>> g 3 <generator object <genexpr> at 0x1013e0780> 4 >>> next(g) 5 0 6 >>> next(g) 7 1 8 >>> next(g) 9 4 10 >>> next(g) 11 9 12 >>> next(g) 13 16 14 >>> next(g) 15 25 16 >>> next(g) 17 36 18 >>> next(g) 19 49 20 >>> next(g) 21 64 22 >>> next(g) 23 81 24 >>> next(g) 25 Traceback (most recent call last): 26 File "<stdin>", line 1, in <module> 27 StopIteration
generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。
1 >>> g = (x * x for x in range(10)) 2 >>> for n in g: 3 ... print(n) 4 ... 5 0 6 1 7 4 8 9 9 16 10 25 11 36 12 49 13 64 14 81
首先generator是可迭代对象,所以可以使用for in循环遍历。该遍历的本质是for in循环内部调用next()函数获取每一个元素,并且捕获StopIteration异常,结束遍历。
三、函数生成器
斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易。
1 >>> def fib(max):
2 ... n, a, b = 0, 0, 1
3 ... while n < max:
4 ... yield b
5 ... a, b = b, a + b
6 ... n += 1
7 ... raise StopIteration('done')
8 ...
9 >>> fib(6)
10 <generator object fib at 0x1013e0780>
11 >>> for i in fib(6):
12 ... print(i)
13 ...
14 1
15 1
16 2
17 3
18 5
19 8
20 >>> g = fib(6)
21 >>> while True:
22 ... try:
23 ... next(g)
24 ... except StopIteration as e:
25 ... print(e.value)
26 ... break
27 ...
28 1
29 1
30 2
31 3
32 5
33 8
34 done
来源:https://www.cnblogs.com/gundan/p/8047495.html