ジェネレータ関数の使い方
pythonのジェネレータ関数は、以下のように関数の中にyieldを記載する
def func():
yield 〇〇
- ジェネレータ関数を宣言して実行すると、yieldの部分で処理がストップし、yieldの〇〇に記載された値が呼び出し元に返される
- その後、再度ジェネレータ関数を呼び出すと、yieldの部分から処理がスタートし、yieldの部分でストップする
- プログラムが終了するまで、何度もジェネレータ関数を呼び出すことができる(その度に、yieldからスタート、yieldで終了する)

- ジェネレータ関数の宣言
def generator(max):
print("generater created")
n = 0
while n < max:
yield n # 呼び出し元にnを返し処理がストップ
print("yield called")
n += 1
gen = generator(10) # ジェネレータの作成、この時点では処理は走らない
a = next(gen) # generatorを呼び出す。「generator created」と表示され、yieldの部分で止まり、yeild nのn(この場合0)が値として返る
print(a) # 0と表示
a = next(gen) # generatorを呼び出す。yield部分からスタートし、「yield called」と表示、nを+1、yieldの部分で停止。n(この場合1)が返る
print(a) # 1と表示
- for内でジェネレータ関数を利用する
n = 0
while n < max:
yield n
n += 1
gen = generator(10)
for i in gen:
print(i)
# n < maxまで、0,1,2,3,4,5,6,7,8,9と表示
ジェネレータの持っているメソッド
また、ジェネレータには以下のメソッドがある
| send() | yieldで停止している箇所に値を送る |
| throw() | 指定した例外が発生して処理が終了させる |
| close() | ジェネレータを正常終了させる |

- send()を使用した例
n = 0
while n < max:
a = yield n
print(a)
n += 1
gen = generator(10)
next(gen)
gen.send(10) # yieldの部分に、sendを創出し、a = 10となり処理が進み、print(10)が実行され、10と表示
- throw()を使用した例
n = 0
while n < max:
yield n
n += 1
gen = generator(10)
for v in gen:
print(v)
if v > 2:
gen.throw(ValueError("Invalid Value")) # ValueErrorを送出して処理を終了させる
- close()を利用した例
n = 0
while n < max:
yield n
n += 1
gen = generator(10)
next(gen)
next(gen)
gen.close() # close()をするとジェネレータ処理が強制終了し、generatorはStopIterationと表示されて利用できなくなる
サブジェネレータ関数の使い方
pythonでは、ジェネレータからジェネレータを呼び出すサブジェネレータという仕組みがある。
このとき、yield fromと記述して、ジェネレータからサブジェネレータを呼び出す。
- ジェネレータからサブジェネレータを呼び出すとき、呼び出し先のサブジェネレータからさらに別のジェネレータを呼び出すときも同様。
- 呼び出し先の最後にreturnを追加することで、呼び出し元に値を返すことができる。

使い方の詳細を以下に記述する
- サブジェネレータの使用例
print("sub_sub_generatorを呼び出しました")
c = yield "sub sub" # yieldの部分で、処理を止めて呼び出し元に値を返す
print("c = {}".format(c))
return "sub sub" # 呼び出し元にsub subを返す
def sub_gen(): # サブジェネレータ(ジェネレータから呼び出される)
print("sub_generatorを呼び出しました")
a = yield "sub"
print("a = {}".format(a))
b = yield from sub_sub_gen() # サブジェネレータを呼び出す。サブジェネレータのreturnの値がbに格納される
print("b = {}".format(b))
return "sub"
def generator():
print("generatorを呼び出しました")
sub = yield from sub_gen() # サブジェネレータを呼び出す。returnの値がsubに格納される
yield sub
g = generator()
i = next(g) # gをyieldまで進める(yield from sub_gen() → yield "sub")
print("返り値 = {}".format(i))
i = g.send(100) # 100を送出して、yieldまで進める(yield from sub_sub_gen() → yield "sub sub" )
print("返り値 = {}".format(i))
i = g.send(200) # 100を送出して、yieldまで進める。(return "sub sub → return "sub" → yield sub)
print("返り値 = {}".format(i))