16. 產生器

產生器(generator)用來產生一些資料,但它不是一次產生全部資料,而是呼叫產生器時才產生並回傳一個資料。

(1) 用小括號及comprehension語法建立產生器

以下是一個例子:

a = (x**2 for x in range(10000000))
print(a)
print(next(a))
print(next(a))
print(next(a))

第1行的指令並沒有一次就產生數量龐大的資料,而是建立一個產生器。 第3~5行的指令next()用來取得產生器的下一個回傳值。

執行結果:

<generator object at 0x000002404819CC80> 0 1 4

(2) 以函式撰寫產生器

產生器函式可以使用yield指令回傳資料,但產生器在回傳資料後並不會結束,而是等下一次呼叫再產生並回傳一個資料。

以下是一個例子:

def mygenerator(n):
    for i in range(n, n+100):
        print('目前處理的i值:', i)
        yield i**2

第4行的yield指令將回傳一個值,等待下一次呼叫產生器時,將再產生一個值並回傳。

主程式:

m = mygenerator(10)
print(m)

print(next(m))
print(next(m))

第1行的建立一個產生器物件;第4及第5行呼叫產生器並分別回傳得到一個回傳值。

執行結果:

<generator object mygenerator at 0x00000286A6C4CC80> 目前處理的i值: 10 100 目前處理的i值: 11 121

問題

以下的程式產生1萬個fibonacci序列清單,然後再逐個取出並顯示。請將fibonacci_list改成產生器的寫法,達成一樣的結果,但不需要花費大量的記憶空間。

def fibonacci_list(num):
    seq = [0, 1]
    idx = 2    
    while idx < num:
        n = seq[idx-1] + seq[idx-2]
        seq.append(n)
        idx+=1
    return seq

#------------------------------
for m in foo_list(9999):
    print(m)

Last updated