ジェネレータはイテレータオブジェクトを返す関数だ。def を使って通常の関数と同じように定義できるけど、ひとつ違うのは return で値を返す代わりに、yield で計算途中の値を返すことができる点。ジェネレータから返されたイテレータオブジェクトは、nextが呼び出されると yield が出てくるまで計算を進めて値を返す。そしてまたnextが呼び出されると、続きの計算をして yield が出てきた時点でまた値を返す。これを繰り返すわけだ。だから、ジェネレータでは while ループの中で yield を使うのが常套手段、というかそうしないとうまく作れないんじゃないかな。
次の例はフィボナッチ数列を出力する。
def fib():
a = 1
b = 1
while True:
yield a
a, b = b, a+b
i = fib()
for c in range(10):
print i.next()
実行結果:
^o^ > python fib.py 1 1 2 3 5 8 13 21 34 55
うまくいった。この例では10個までしか出力してないけど、コードをよく見ればわかるとおり、終了しない無限ループになっている。言い換えると無限に値を生成できるってこと。これはリストやファイルオブジェクトから作るイテレータとは違うところだ。