ジェネレータ

 ジェネレータ関数

 ジェネレータとは一種の関数です。普通の関数は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()