python 之生成器 yield
阿新 • • 發佈:2018-12-18
一、生成器的概念綜述
一個帶有 yield 的函式就是一個 generator,它和普通函式不同,生成一個 generator 看起來像函式呼叫,但不會執行任何函式程式碼,直到對其呼叫 next()(在 for 迴圈中會自動呼叫 next())才開始執行。雖然執行流程仍按函式的流程執行,但每執行到一個 yield 語句就會中斷,並返回一個迭代值,下次執行時從 yield 的下一個語句繼續執行。看起來就好像一個函式在正常執行的過程中被 yield 中斷了數次,每次中斷都會通過 yield 返回當前的迭代值。
yield 的好處是顯而易見的,把一個函式改寫為一個 generator 就獲得了迭代能力,比起用類的例項儲存狀態來計算下一個 next() 的值,不僅程式碼簡潔,而且執行流程異常清晰。
廖雪峰大神寫的yield的文章
https://www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/
二、經典案例,生產者消費者模型
瞭解該模型,需要知道兩個函式的呼叫過程,通過debug模式逐步執行:
1.
consumer.send(None) data = yield producer = produce(consumer) 進入for迴圈三句話;
執行produce列印語句; consumer.send(data) data = yield(第二次到達,此時yield帶來了data的資料並賦值給data變數)
執行consume列印語句; data = yield(第三次到達) yield 進入for迴圈三句話;
yield 執行 print('現在執行yield之後的函式') 這句話。
執行produce列印語句;開始迴圈。
由此可知:每個函式在被呼叫過程中,到達yield關鍵詞後,立馬在yield這地方停止,並跳出該函式,進行繼續進行其它程式碼的執行;當該函式再次被呼叫時候,從yield停止的地方開始執行函式後面的程式碼。
import random def get_data(): """返回0到9之間的3個隨機數""" return random.sample(range(10), 3) def consume(): """顯示每次傳入的整數列表的動態平均值""" running_sum = 0 data_items_seen = 0 while True: data = yield data_items_seen += len(data) running_sum += sum(data) print('The running average is {}'.format(running_sum / float(data_items_seen))) def produce(consumer): """產生序列集合,傳遞給消費函式(consumer)""" while True: data = get_data() print('Produced {}'.format(data)) consumer.send(data) yield if __name__ == '__main__': consumer = consume() consumer.send(None) producer = produce(consumer) for _ in range(10): print('Producing...') next(producer)