列表推導與生成器表達式
當我們創建了一個列表的時候,就創建了一個可以迭代的對象:
代碼如下:
>>> squares=[n*n for n in range(3)]
>>> for i in squares:
print i
0
1
4
這種創建列表的操作很常見,稱為列表推導。但是像列表這樣的迭代器,比如str、file等,雖然用起來很方便,但有一點,它們是儲存在內存中的,如果值很大,會很麻煩。
而生成器表達式不同,它執行的計算與列表包含相同,但會迭代的生成結果。它的語法與列表推導一樣,只是要用小括號來代替中括號:
代碼如下:
>>> squares=(n*n for n in range(3))
>>> for i in squares:
print i
0
1
4
生成器表達式不會創建序列形式的對象,不會把所有的值都讀取到內存中,而是會創建一個通過迭代并按照需求生成值的生成器對象(Generator)。
那么,還有沒有其它方法來產生生成器呢?
例子:斐波那契數列
例如有個需求,要生成斐波那契數列的前10位,我們可以這樣寫:
代碼如下:
def fib(n):
result=[]
a=1
b=1
result.append(a)
for i in range(n-1):
a,b=b,a+b
result.append(a)
return result
if __name__=='__main__':
print fib(10)
數字很少時,函數運行良好,但數字很多時,問題就來了,顯然生成一個幾千幾萬長度的列表并不是一個很好的主意。
這樣,需求就變成了:寫一個可以生成可迭代對象的函數,或者說,不要讓函數一次返回全部的值,而是一次返回一個值。
這好像與我們的常識相違背,當我們調用一個普通的Python函數時,一般是從函數的第一行代碼開始執行,結束于return語句、異?;蛘吆瘮到Y束(可以看作隱式的返回None):
代碼如下:
def fib(n):
a=1
b=1
for i in range(n-1):
a,b=b,a+b
return a
if __name__=='__main__':
print fib(10)
>>>
1 #返回第一個值時就卡住了
函數一旦將控制權交還給調用者,就意味著全部結束。函數中做的所有工作以及保存在局部變量中的數據都將丟失。再次調用這個函數時,一切都將從頭創建。函數只有一次返回結果的機會,因而必須一次返回所有的結果。通常我們都這么認為的。但是,如果它們并非如此呢?請看神奇的yield:
新聞熱點
疑難解答