1. 程式人生 > >Python小技巧5:需要動態生成列表的時候,考慮使用生成器替代

Python小技巧5:需要動態生成列表的時候,考慮使用生成器替代

典型程式碼:

def mygen():
    i = 0
    while i < 100:
        yield i
        i += 1


if __name__ == '__main__':
    gen = mygen()
    for item in gen:
        print(item)

什麼是生成器:

生成器是一個包含yield表示式的函式,只要一個函式中有了yield表示式,當呼叫這個函式的時候,函式體的程式碼壓根就不會執行,它只是會返回一個生成器物件。如果訪問一個生成器迭代器,每次訪問到的值都是動態生成的(比如典型程式碼中的變數i),即是yield右邊的值,並凍結當前狀態,等待下一次訪問。對於生成器物件可以將其理解為一種值的順序生成規則的描述,生成器物件會一直維護自己的生成規則上下文,直到結束(當然,也可以不結束)。

應用場景:

如果需求是動態的生成一個列表,然後其它函式會一次性訪問這個列表中的項,做相應的處理工作。

帶來的好處:

1. 不必返回整個列表物件,只返回生成規則描述,如果元素數量較大,可以節省大量記憶體。生成器甚至可以生成一個無限序列,只要生成規則永不停止即可。

2. 邏輯清晰,一眼就能看到值是如何返回的。

注意的點:

生成器物件是有狀態的,只能訪問一次。這也很容易理解,因為生成器只是一個值的生成規則,加上其上下文,不像列表一樣儲存了所有的值。

也可以使用原生的迭代器協議訪問生成器,但是需要手動處理迭代器結束時的StopIteration異常:

    gen = mygen()
    while True:
        try:
            data = next(gen)
            print(data)
        except StopIteration:
            print('Iteration done')
            break