列表生成式 List Comprehensions 列表生成式是Python內置的非常簡單卻強大的可以用來創建list的生成式。 簡單的數值範圍的list可以使用一下方式生成: 稍微複雜的可以利用list生成式: 迴圈後面還可以加上if判斷,例如僅篩選出偶數的平方: 使用兩層迴圈可以生成全排列: 生 ...
列表生成式
List Comprehensions 列表生成式是Python內置的非常簡單卻強大的可以用來創建list的生成式。
簡單的數值範圍的list可以使用一下方式生成:
>>> list(range(1, 11))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
稍微複雜的可以利用list生成式:
>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
迴圈後面還可以加上if判斷,例如僅篩選出偶數的平方:
>>>[x*x for x in range(1, 11) if x%2 == 0]
[4, 16, 36, 64, 100]
使用兩層迴圈可以生成全排列:
>>> [m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
生成器
生成器(generator)是一種一邊迴圈一邊計算的機制。
生成器的應用場景:只需要獲得list中的前幾個元素,節省存儲空間;需要的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>
g是一個generator,不可以直接獲得值,可以通過next()函數獲得generator的下一個返回值,沒有跟多元素時,拋出StopIteration的錯誤。
另一種獲得generator值得方式:因為generator是可迭代對象,更好的方式是通過使用for迴圈來獲得其值,這種方式不用關心StopIteration的錯誤。使用方式如下:
>>> g = (x * x for x in range(10))
>>> for n in g:
... print(n)
...
0
1
4
9
16
25
36
49
64
81
如果推算的演算法比較複雜,用類似列表生成式的for迴圈無法實現時,還可以使用函數來實現。
比如著名的斐波拉契數列,出第一個和第二個數外,任意一個數都可以由前兩個數相加得到:
1,1,2,3,5,8,13,21,34,...
該數列使用列表生成式無法實現,使用函數的實現方式如下:
def fib(max):
n, a, b = 0, 0, 1
while n < max:
print(b)
a, b = b, a+b
n = n + 1
return 'done'
要把fib函數變成generator,只需要把print(b)改為yield b就可以了:
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'
generator與函數執行流程的差異:函數是順序執行,遇到return語句或者最後一行函數語句就返回;而generator函數每次調用next()的時候執行,遇到yield語句返回,再次執行時從上次返回的yield語句處繼續執行。
如果想要拿到函數中的返回值,必須捕獲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