Windows 10家庭中文版,Python 3.6.4,
上午看過了一篇講Python生成器的博文:
提高你的Python: 解釋‘yield’和‘Generators(生成器)’ (英文原文)
這篇博文講的挺好的,但在讀完后,自己仍然對yield、send、yield返回值等概念不清楚,於是,做了兩個小試驗。
試驗一:yield語句的返回值
1 def xyz(): 2 print('xyz 0') 3 while True: 4 print('xyz 1') 5 data = yield 2 6 print('xyz 2, data = ', data) 7 8 if __name__ == '__main__': 9 mg = xyz() 10 for _ in range(3): 11 print('\nmain: _ = ', _) 12 print('main:', next(mg))
結果:
main: _ = 0
xyz 0
xyz 1
main: 2
main: _ = 1
xyz 2, data = None
xyz 1
main: 2
main: _ = 2
xyz 2, data = None
xyz 1
main: 2
介紹:
定義了生成器函數xyz(),使用語句data = yield 2;
舊的想法:data會等於2;
測試結果:data等於None;
執行next(mg)函數時,控制權交給了xyz()函數——第一次執行xyz()函數,輸出了xyz 0,再進入循環,執行yield語句;
yield生成了2,控制權和生成的值2返回給調用函數——語句執行完畢后會給data賦值吧?或者等下一次給data賦值?,輸出main: 2;
此時,生成器停在了這里;
再次執行next(mg)時,控制器又交給了xyz()函數,從上一次執行yield語句的下一句開始執行,於是,輸出了“xyz 2, data = None”,上一次執行yield時,給data的值居然是None,孤以為會是2呢!
試驗二:生成器的send函數和yield返回值語句的關系
1 def xyz(): 2 print('xyz 0') 3 while True: 4 print('xyz 1') 5 data = yield 2 6 print('xyz 2, data = ', data) 7 8 if __name__ == '__main__': 9 print('main 0') 10 mg = xyz() 11 print('main 1') 12 mg.send(None) # 第一次必須如此!!! 13 print('main 2') 14 for _ in range(3): 15 print('\nmain 3') 16 mg.send(_) 17 print('main 4')
結果:
main 0
main 1
xyz 0
xyz 1
main 2
main 3
xyz 2, data = 0
xyz 1
main 4
main 3
xyz 2, data = 1
xyz 1
main 4
main 3
xyz 2, data = 2
xyz 1
main 4
介紹:
第一次必須執行mg.send(None),為什么這樣孤還沒搞清楚,和生成器的內部實現有關;
在調用send函數時,控制權交給xyz()函數,執行到yield語句停止,再將控制器返回給調用函數;
主函數中循環執行send函數;
第一次發送了0,結果輸出xyz 2, data = 0,這里的data不是None了,即便之前有調用send(None),這是否可以認為,yield語句是在 控制權交給生成器所在函數后才執行的?
xyz()中的循環執行到print('xyz 1')再次停止,控制器返回給主函數;
之后再把1、2發送給生成器;
總結
next(generator), generator.send(data)都會將控制權交給生成器函數;
yield語句是在獲取控制權后執行,而不是之前,之前程序掛在這里了,同時保存了上下文;
下面三條語句的解釋:
yield # 返回給主調函數None
data = yield # 返回給主調函數None,並把send的值賦值給data;如果是使用next獲取了控制權,那么,調用next處獲得None;
data = yield 2 # 返回給主調函數next(),並把send的值賦值給data;
本文開頭的博文大家要看看,這樣才可以更好地理解孤這篇文檔,結合那篇博文及這兩個試驗,孤以為自己掌握了Python生成器的80%了吧,更多就需要看官網了。
----
本來想找個Python官方鏈接給大家的,可是啊,它的這個頁面一時訪問不了(為什么呢?):大家自行搜索官方、權威文檔吧,也會講解的更詳細。
https://docs.python.org/3/tutorial/index.html