pythonでイテラブルなオブジェクトを作成するジェネレータ関数について
yieldを使ってジェネレータ関数を作成する
pythonのfor文ではイテラブルなりストやタプル、range()を使って変域を指定できます。
リストと同じようなものをジェネレーター関数といい、その作成にyieldを使います。
#ジェネレータ関数
def g():
for a in range(3):
yield a
print(g()) # generatorオブジェクトが返される
print(type(g())) # クラスがgeneratorになっている
---実行結果---
<generator object g at 0x0179C300>
<class 'generator'>
ジェネレータ関数g()をprintしても値はかえってこないです。
typeでみるとgeneratorとなっています。
# g()のaの値は0,1,2となってるはず?
for b in range(3):
print(b) # 0,1,2と表示される
---実行結果---
0
1
2
ジェネレーター関数ではなく、単純にfor文で実行した結果は0,1,2がはいっています。
ジェネレーター関数から値を取り出す
def g():
for a in range(3):
yield a
## g()のaの値を取り出す方法 list(), tuple(), set()で取り出す
print(list(g())) # [0, 1, 2]が返される
print(tuple(g())) # (0, 1, 2)が返される
print(set(g())) # {0, 1, 2}が返される
# g()のaの値を取り出す方法 forループで取り出す
for c in g(): # g()をリストのようなイテラブルなオブジェクトとして利用
print(c) # 0,1,2と表示される
# g()のaの値を取り出す方法 next()で取り出す
d = g()
print(next(d)) # 0が返される
print(next(d)) # 1が返される
print(next(d)) # 2が返される
#next関数は先頭から価を順番に取り出すもの。もう一回print(next(d)) をやると次の価は無いので、StopIterationエラーになる
実行結果
## g()のaの値を取り出す方法 list(), tuple(), set()で取り出す
[0, 1, 2]
(0, 1, 2)
{0, 1, 2}
# g()のaの値を取り出す方法 forループで取り出す
0
1
2
# g()のaの値を取り出す方法 next()で取り出す
0
1
2
for文で for c in g()というようにジェネレーター関数をイテラブルなオブジェクトとして利用できます。ジェネレーター関数は一つずつ値を返してくれます。ジェネレートした値をいれてlistとしてもtupleとしても取り出せます。
シンプルな例
def gene():
yield "a"
yield "b"
yield "c"
for i in gene():
print(i)
実行結果
a
b
c
ジェネレータ関数はforなどで取り出さないと呼び出しただけではreturnのように値を返さないので、メモリの節約になるそうです。
参考