about 3 years ago

Consider Generators Instead of Returning Lists

考慮下面兩種版本,一個用 list ,另一個用 generator

def index_words(text):
    result = []
    if text:
        result.append(0)
    for index, letter in enumerate(text):
        if letter == ' ':
            result.append(index + 1)
    return result

address = 'Four score and seven years ago...'
result = index_words(address)
print(result[:3]) # [0, 5, 11]
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))

使用 generator 比較簡潔,因為減少了 list 操作,讓程式意圖更明顯。

另一個 generator 的好處是更有效率地使用記憶體,畢竟不需要有個 list 存全部的資料。

import itertools

def index_file(handle):
    offset = 0
    for line in handle:
        if line:
            yield offset
        for letter in line:
            offset += 1
            if letter == ' ':
                yield offset

with open('/tmp/address.txt', 'r') as f:
    it = index_file(f)
    results = itertools.islice(it, 0, 3)
    print(list(results))

不管檔案再大,上面的程式都能處理。

← Effective Python 心得筆記: Item 15 Effective Python 心得筆記: Item 17 →
 
comments powered by Disqus