通過列表list生成器,我們可以直接創建一個列表
>>> x = list(range(1,11)) >>> x [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
但是,受到內存的限制,列表的容量是有限的,而且創建一個包含100萬1個億的列表時候,不僅會占用很大的儲存空間,如果有事我們只要訪問前面幾個元素,那后面大多數元素都白白浪費了。而且運作效率低下。
如果列表元素可以按某種算法推算出來,那我們是否可以在循環的過程中不斷推算出后面的元素呢?這樣就不必要創建一個完整的list列表了,從而提升程序的效率。在python中,這種一邊循環一邊計算的機制,稱為生成器generator
要創建一個generator,有很多方法:
第一種方法很簡單,就是只要把一個列表生成試的 [ ] 改成 ( ) 就可以創建一個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 0x00000000035BC410>
L 是一個list, 而 G 是一個generator:它們在創建時候最基本的不同就list是 [ ] ,而generator是 ( ) 。
我們可以直接打印出list的全部元素,但是怎么打印出generator的全部元素呢?
>>> g <generator object <genexpr> at 0x00000000035BC410>
如果要一個個打印出來,可以通過next()函數來獲得generator的下一個返回值。
>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> next(g)
16
>>> next(g)
25
>>> next(g)
36
>>> next(g)
49
>>> next(g)
64
>>> next(g)
81
>>> next(g)
Traceback (most recent call last):
File "<pyshell#18>", line 1, in <module>
next(g)
StopIteration
generator保存的是算法,每次調用 next(g)的時候才會計算 g 的下一個元素值,直到計算到最后一個元素,沒有下一個元素時,會返回stopIteration的錯誤。
當然,上面這種不停調用next (g)這種方法實在是太繁瑣了,正確的方法是使用for循環,因為generator也是一個可迭代對象:
>>> g = (x * x for x in range(10)) >>> for n in g: ... print(n) ... 0 1 4 9 16 25 36 49 64 81
我們創建一個generator之后,基本上不會調用next(),而是通過for循環來迭代他,並且不用關心StopIteration的錯誤
generator非常強大,如果推算的算法比較復雜,用類似列表生成試的for循環無法實現的時候,我還可以用函數來實現。
