Python 簡易手冊
單元 50 - 產生器
關鍵字 (keyword) yield 用作產生數值,只能用在函數 (function) 中,使之成為產生器 (generator) 函數,舉例如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 產生器函數 def do_something(n): for i in range(n): if i % 2 != 0: # 產生數字 yield i # 呼叫產生器函數 a = do_something(10) # 依序取得產生器函數產生的數字 print(next(a)) print(next(a)) print(next(a)) print(next(a)) print(next(a)) # 檔名: yield_demo.py # 說明: 《Python簡易手冊》的範例 # 網址: http://kaiching.org # 作者: Kaiching Chang # 時間: 2024 年 3 月 |
第 6 行,關鍵字 yield 在函數 do_something() 中產生 for 迴圈取得的奇數
1 2 3 4 5 6 | # 產生器函數 def do_something(n): for i in range(n): if i % 2 != 0: # 產生數字 yield i |
單元 44 - 函數與 return 陳述介紹如何定義函數,單元 23 - for 陳述介紹如何使用 for 迴圈 (loop) ,單元 38 - 序對與 Range介紹 range 資料型態,這裡判斷奇數是用 if 陳述 (statement) ,單元 20 - if 陳述介紹 if 的用法。
第 9 行呼叫產生器函數
8 9 | # 呼叫產生器函數 a = do_something(10) |
下面用五次內建函數 (built-in function) next() 印出產生器 a 的值
10 11 12 13 14 15 | # 依序取得產生器函數產生的數字 print(next(a)) print(next(a)) print(next(a)) print(next(a)) print(next(a)) |
產生器其實就是迭代器 (iterator) 的語法糖,所以跟迭代器一樣是用 next() 取值,此例執行結果如下
> python yield_demo.py |
1 3 5 7 9 |
> |
單元 66 - 迭代器會介紹如何定義迭代器。
原本函數中只能用 return 或 yield 二選一,基本上就是讓函數只能回傳或是只能產生,後來 Python 允許在產生器函數中用 return 陳述,這樣產生器函數除了產生外有回傳的功能,倒是取得回傳值要用另一個委派函數,以 yield from 取得回傳值 (return value) ,舉例如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | # 產生器函數 def do_something(n): # 暫存總和 sum = 0 # 進行產生及加總 for i in range(n): if i % 2 != 0: # 進行加總 sum += i # 產生數字 yield i # 回傳總和 return sum # 產生器的委派函數 def do_something2(n): y = yield from do_something(n) print(y) # 呼叫函數 a = do_something2(10) # 印出產生的值 for i in a: print(i) # 檔名: yield_demo2.py # 說明: 《Python簡易手冊》的範例 # 網址: http://kaiching.org # 作者: Kaiching Chang # 時間: 2024 年 3 月 |
上例的 do_something() 加入 sum 計算產生所有數字的總和,最後也回傳 sum ,如果要使用 do_something() 的回傳值,就在委派函數 do_something2() 中以 yield from 取得
15 16 17 18 | # 產生器的委派函數 def do_something2(n): y = yield from do_something(n) print(y) |
這裡是印出 do_something() 的回傳值,然後執行部分是用 do_something2() 建立產生器變數,以 for 迴圈印出產生器變數的值
20 21 22 23 24 | # 呼叫函數 a = do_something2(10) # 印出產生的值 for i in a: print(i) |
注意,如果是用 do_something() 建立產生器變數,那就不會取得回傳值,此例執行結果如下
> python yield_demo2.py |
1 3 5 7 9 25 |
> |
參考資料
- https://docs.python.org/3/reference/simple_stmts.html#the-yield-statement
- https://docs.python.org/3/tutorial/classes.html#generators
- https://docs.python.org/3/tutorial/classes.html#generator-expressions