Python中什么時候使用生成器?


編者注:本文主要參考了《Python核心編程(第二版)》

說到生成器,先說說列表解析。列表解析可以動態創建列表。

[expr for iter_var in iterable if cond_expr]

該句的核心是 for循環,它迭代了iterable對象的所有條目。如果滿足cond_expr(條件表達式),則前面的expr(表達式)應用於該成員。最后生成的是滿足條件的元素的該表達式的列表。對於lambda,map(),filter()等可以通過列表解析簡化為一個列表解析式。 首先看看這三個函數的作用:

map(lambda x:x**2, range(6))
>>>[0, 1, 4, 9, 16, 25]

lambda 輸入參數:輸出表達式    允許創建一行函數對象,不用def定義,簡化代碼
map(操作,需要操作的列表)       對所有列表成員應用一個操作

可以用列表解析來簡化上面的操作:

[x**2 for x in range(6)]
>>>[0, 1, 4, 9, 16, 25]

同樣也可以用列表解析來簡化filter()操作,比如:

seq = [11, 10, 1, 9, 10, 2, 3, 44, 12, 11]
print filter(lambda x: x % 2, seq)
>>>[11, 1, 9, 3, 11]

可以用列表解析來簡化上面的操作:

print [x for x in seq if x % 2]
>>>[11, 1, 9, 3, 11]

生成器是列表解析的一個拓展。
(expr for iter_var in iterable if cond_expr)
它與列表解析器非常相似,且語法基本相同,但不是真正創建列表而是生成一個生成器。這個生成器在每次計算出一個條目后,把這個條目“產生(yield)出來”,生成器表達式使用了“延遲計算(lazy evaluation)”,所以它使用內存上更有效。

print (x for x in seq if x % 2)
>>><generator object <genexpr> at 0x00000000025B6AB0>

那到底什么時候使用生成器呢?

當創建列表只是一共中間過程的時候,為了避免創建龐大的列表,我們可以使用生成器表達式來完成。比如,我們要計算一篇txt文本的單詞數時,我們沒必要先將列表生成再計算單詞數。

f = open('*.txt','r')
len([word for line in f for word in line.split()]) #使用列表解析,先生成列表后計數
len(word for line in f for word in line.split())   #使用生成器,對返回的生成器計數,沒有生成列表

所做的只是把方括號去掉,不但少了兩個字節,更節省了內存。
這讓我想起了使用xrange()代替range(),道理是一樣的。xrange返回一個生成器,而range返回一個列表。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM