第16條:考慮用生成器來改寫直接返回列表的函數(shù)
如果一個函數(shù)要產(chǎn)生一系列結(jié)果抵皱,最簡單的做法是把這一系列結(jié)果放在一個列表里,然后返回列表泽裳。
但是這里有個問題蝉稳,如果我們產(chǎn)生的結(jié)果特別多,比如讀取一個很大的文件的所有行劳闹,這時就很容易造成內(nèi)存異常院究。
所以,正常情況下本涕,我們不會去使用一個列表去存儲這種占內(nèi)存特別多的一系列結(jié)果业汰,而是采用一種可以不斷獲取數(shù)據(jù)的方法來實(shí)現(xiàn),這就是之前說到的生成器菩颖。
先看例子:
def index_words(text):
result = []
if text:
result.append(0)
for index, letter in enumerate(text):
if letter == ' ':
result.append(index + 1)
return result
這個是一個從字符串中取出每個單詞首字母位置的例子样漆,運(yùn)行看下效果:
address = 'Four score and seven years ago...'
result = index_words(address)
print(result[:3])
>>>
[0, 5, 11]
可以看出上面的方法可以完成要求,但是代碼稍顯冗余晦闰,將近一般的代碼用來實(shí)現(xiàn) result 的 append 上面放祟,而現(xiàn)在的重點(diǎn)是獲取首字母位置,如果用生成器來實(shí)現(xiàn)的話呻右,可以這樣:
def index_words_iter(text):
if text:
yield 0
for index, letter in enumerate(text):
if letter == ' ':
yield index + 1
result = list(index_words_iter(address))
print(result[:3])
>>>
[0, 5, 11]
換成生成器后跪妥,就完全省去了 result 的 append 相關(guān)代碼,而且声滥,目的很清晰眉撵,就是獲取每個單詞的首字母位置。這里的重點(diǎn)是 yield 表達(dá)式落塑,它會在函數(shù)運(yùn)行的時候返回迭代器纽疟,每次調(diào)用迭代器后,會推到下一次的 yield 位置憾赁,然后由迭代器返回 yield 返回的值污朽。這樣如果傳入的字符串是由一個很大的文本文件讀出來的,就不用擔(dān)心占用太多的內(nèi)存龙考。