Python列表生成器與生成器
阿新 • • 發佈:2019-01-04
一、列表生成器
列表生成式即List Comprehensions
>>>list(range(1,5))
[1, 2, 3, 4]
>>>[x * x for x in range(1, 5)] // 即直接生成x平方的列表
[1, 4, 9, 16]
// 加判斷 只生成偶數的平方
[x * x for x in range(1, 11) if x % 2 == 0]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
// 兩層迴圈
// range(1,5)為[1,2,3,4] range(5,9)為[5,6,7,8 ]
>>>x + y for x in range(1, 5) for y in range(5, 9)
[6, 8, 10, 12]
二、生成器
上面我們提到的列表生成器,是直接建立了一個列表,顯而易見,當數量很大時,直接建立一個列表,相當佔記憶體。
所以,如果列表元素可以按照某種演算法推算出來,那我們是否可以在迴圈的過程中不斷推算出後續的元素呢?這樣就不必建立完整的list,從而節省大量的空間。在Python中,這種一邊迴圈一邊計算的機制,稱為生成器: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>
我們可以通過 next()
函式來獲得生成器內的資料
>>> 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 "<stdin>", line 1, in <module>
StopIteration
當我們建立好了一個生成器之後,可以用for
迴圈讀取資料
此外:
當一個函式內,我們用到了 yeild
函式,那麼這個函式就變成了一個generator
比如,斐波拉契數列(Fibonacci):
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'
>>> f = fib(6)
>>> f
<generator object fib at 0x104feaaa0>
這裡,最難理解的就是generator
和函式的執行流程不一樣。函式是順序執行,遇到return
語句或者最後一行函式語句就返回。而變成generator
的函式,在每次呼叫next()
的時候執行,遇到yield
語句返回,再次執行時從上次返回的yield
語句處繼續執行。
獲得數列的結果:
>>> for n in fib(6):
... print(n)
...
1
1
2
3
5
8