前面提到,對於數據量很大時,可以用生成器表達式代替列表推導,同樣,當一個函數返回列表且數據量很大時,應該考慮使用生成器。
案例1:獲取字符串中每個單詞的首字母
def index_words(text):
result = []
if text:
result.append(0)
for index,letter in enumerate(text):
if letter == ' ':
result.append(index+1)
return result
if __name__ == "__main__":
text = "Four score and seven years ago..."
result = index_words(text)
print(result)
上面的函數,在返回前,將所有的結果存放到result
列表中。如果文本輸入量很大,就會導致程序耗盡內存並崩潰。如果使用生成器,則可以應對任意長度的輸入數據。
生成器是使用yield表達式的函數。
- 調用生成器函數時,它並不會真的運行,而是會返回迭代器。每次在迭代器上面調用
next
函數,迭代器會把生成器推進到下一個yield
表達式那裏。 - 生成器調用
yield
的每一個值,都會由迭代器返回給調用者。 - 無論輸入量多大,生成器產生一系列輸出,都不會影響執行時所消耗的內存。
利用生成器改寫的上述函數爲:
def index_words(text):
if text:
yield 0
for index,letter in enumerate(text):
if letter == " ":
yield index+1
if __name__ == "__main__":
text = "Four score and seven years ago..."
it = index_words(text) # 迭代器
result = list(it)
print(result)
定義這種生成器函數的時候,唯一需要注意的就是:函數返回的那個迭代器,是有狀態的,調用者不應該反覆使用它。