ジェネレータ
ジェネレータ関数
ジェネレータとは一種の関数です。普通の関数はreturn文で結果を返しますが、ジェネレータ関数はyield文で結果を返します。yield文がreturn文と何が違うかというと、yield文が実行されると、関数は処理を一旦止めて、再び実行されるまで待ちます。
ジェネレータ関数の使い方ですが、ジェネレータ関数は呼び出されたと、イテレータオブジェクトを返します。そのイテレータオブジェクトのnextメゾットを実行することで、ジェネレータ関数は実行されます。
フィボナッチ数列を返すジェネレータ関数を作って試してみましょう。
フィボナッチ数列とは
1回目 :0
2回目 :1
3回目以降:2つ前の数+1つ前の数
上記の規則で並んでいる数字のことです。
つまり
0, 1, 0+1, 1+1, 1+2, 2+3, 3+5, 5+8, 8+13・・・
要するに
0, 1, 1, 2, 3, 5, 8, 13, 21, 34,・・・
という風に並んでいます。これを踏まえて作ってみましょう。
#coding: shift-jis
def get_fib():
''' フィボナッチ数列を返すジェネレータ関数'''
i = 1
while True: ←無限ループの設定
if i == 1:
p1 = 0
yield 0
elif i == 2:
p2 = 1
yield 1
else :
p3 = p1 + p2
p1 = p2
p2 = p3
yield p3
i += 1
fib = get_fib() ←ジェネレータ関数を呼び出す
for j in range(10):
print fib.next()
raw_input()
出力画面
0
1
1
2
3
5
8
13
21
34
またジェネレータ関数はfor文の中に組み込めます。但し無限ループにならないように注意しましょう。次の例は上でやった結果と同じ出力画面になります。
#coding: shift-jis
def get_fib():
''' フィボナッチ数列を返すジェネレータ関数'''
i = 1
while True: ←無限ループの設定
if i == 1:
p1 = 0
yield 0
elif i == 2:
p2 = 1
yield 1
else :
p3 = p1 + p2
p1 = p2
p2 = p3
yield p3
i += 1
for j in get_fib():
if j > 50 :
break
print j
raw_input()