一、生成器定義 通過列表生成表達式,我們可以直接創建一個列表。但是,受到記憶體限制,列表容量肯定是有限的。所以,如果列表元素可以按照某種演算法推算出來,那我們是否可以在迴圈的過程中不斷推算出後續的元素呢?這樣就不必創建完整的list,從而節省大量的空間。在Python中,這種一邊迴圈一邊計算的機制,稱為 ...
一、生成器定義
通過列表生成表達式,我們可以直接創建一個列表。但是,受到記憶體限制,列表容量肯定是有限的。所以,如果列表元素可以按照某種演算法推算出來,那我們是否可以在迴圈的過程中不斷推算出後續的元素呢?這樣就不必創建完整的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