2021年6月7日 星期一

[Python]學習筆記_Generator

 我決定從此以後不要再被Python Generator弄得七葷八素,學了就要會!



Generator是什麼?


在Python裡,跳脫函式(Function)可透過兩個保留字

1. Return: 將執行序返還呼叫者,並且終結函式內一切變數;下次再呼叫此函式時,會從函式第一行開始執行。

2. Yield: 同樣也將執行序返還呼叫者,但在記憶體內保留函式內一切變數,下次再呼叫此函式時,會從Yield的下一個指令開始進行


而以Yield作為返還手段的函式即為Generator,雖同樣透過def宣告,卻是一種能記憶函式執行狀態的特殊物件,而非純函式;且內部資料在Yield返回後不會消滅。

備註 : 根據這些特性猜測應該帶有狀態變數、且資料存在Heap中。

實作Generator的基本套路101

1. 初始化片段(Initialization) : 將只想執行一次的程式碼片段、變數寫在這裡

2. 執行片段(Iteration) : 在此安排 傳入資料/計算/傳出資料 的固定流程,視情況套上迴圈以及結束條件;

3. 解構片段(Finalization) : (通常沒什麼事好做,硬要為了類似物件的生命週期放上這段)


def a_generator():
    #1. Initialization, codes prior to WHILE would be execute only once per instance. 
    # whatever how many times being called
    data_in_heap = range(0,100) # a sequence as : 0,1,2,3,4,5
    index_in_heap = 0

    #2. Iternation, YIELD are being surrrounded by WHILE. caller would re-entry through.
    # output are expected to be : 1,2,3,4,5
    while True:
        input = yield # first yield, 
        output = data_in_heap[index_in_heap] + input #offset 
        yield output # second yield
        index_in_heap += 1

    #3. Finalization, surely this would only executed once. 
    return

呼叫端(Caller)呼叫方法基本套路101

  1. 建構Generator實例(Instance)  : Generator是個物件,理當建構後使用;建構後的Generator只配置(Allocate)了記憶體,未呼叫前只會停在第一行等待被執行
  2. 執行Generator : 透過以下方式可以執行Generator,並傳遞資料
    1. Value = Next() : 將會執行Generator程式碼,並在遇到下一個Yield後返還;若返還時的Yield右邊有變數,則將變數值交付給Caller;否則會是None
    2. Value = Send(arg) : 將arg傳入Generator內某個內建暫存區? 並執行Generator程式碼,同樣也是遇到下一個Yield後返還;若返還時的Yield右邊有變數,則將變數值交付給Caller;否則會是None

a_generator_instance = a_generator() #Instanize a generator

while True:
    yield_out_value = next(a_generator_instance) #execute the generator : move to first yield
    yield_out_value = a_generator_instance.send(1) #execute the generator : start from first yield and move to second yield.
    print(yield_out_value)
    pass
    

Yield保留字除了控制程式流以外也肩負了對呼叫端(Caller)交換資料的窗口,端看放在變數的左右邊決定

  1. input = yield : Generator執行到此將執行序返還,因為Yield右邊沒東西,沒有輸出對象,因此呼叫端不會收到任何返還值,下次再進入時,將來自呼叫端的傳入值取出到等號左邊的變數中;
  2. yield output: 將變數值輸出;Generator執行到此將執行序返還呼叫端時,一併將輸出值交付


最後附上飯粒,筆記Generator執行流程

乍看猶如娘家譜系圖般的複雜,但用來做順序控制很好用

  • 綠色:呼叫
  • 紫色:函式內執行
  • 紅色:Yield返還





2 則留言: