我決定從此以後不要再被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
- 建構Generator實例(Instance) : Generator是個物件,理當建構後使用;建構後的Generator只配置(Allocate)了記憶體,未呼叫前只會停在第一行等待被執行
- 執行Generator : 透過以下方式可以執行Generator,並傳遞資料
- Value = Next() : 將會執行Generator程式碼,並在遇到下一個Yield後返還;若返還時的Yield右邊有變數,則將變數值交付給Caller;否則會是None
- 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)交換資料的窗口,端看放在變數的左右邊決定
- input = yield : Generator執行到此將執行序返還,因為Yield右邊沒東西,沒有輸出對象,因此呼叫端不會收到任何返還值,下次再進入時,將來自呼叫端的傳入值取出到等號左邊的變數中;
- yield output: 將變數值輸出;Generator執行到此將執行序返還呼叫端時,一併將輸出值交付
最後附上飯粒,筆記Generator執行流程
乍看猶如娘家譜系圖般的複雜,但用來做順序控制很好用
- 綠色:呼叫
- 紫色:函式內執行
- 紅色:Yield返還
專業 長知識了
回覆刪除很像C#中 IEnumerator.MoveNext 與 yield return
回覆刪除