先ほどの記事で、フィボナッチ数列を生成するイテレータを定義したが、よく考えればジェネレータで十分だった。
ジェネレータでフィボナッチ数列
ジェネレータでは、生成した値を返すときに、returnではなくyieldを使う。yieldを使うと実行権は呼び出し元に戻るが、次にnext()が実行されると実行の流れはジェネレータ内に戻される。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | >>> def fib_gen(): ... i, j = 0, 1 ... while True: ... i, j = j, i + j ... yield i ... >>> fg = fib_gen() >>> fg.next() 1 >>> fg.next() 1 >>> fg.next() 2 >>> fg.next() 3 >>> fg.next() 5 >>> for i in range(10): ... fg.next() ... 8 13 21 34 55 89 144 233 377 610 >>> |
まとめ
ジェネレータを使うと、イテレータを使うより簡潔に繰り返しを記述できた。フィボナッチ数列を作るなどといった単純な処理であればジェネレータ式のほうが簡潔でよいと思う。逆に、生成後に、繰り返しの条件を変える必要がある場合は、ジェネレータでは記述しにくい気がする。
※イテレータは、内部変数や、nextメ()そのものを書き換えることができる。
1 2 3 4 5 6 7 | >>> i = FibIter(100) >>> list(i) [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] >>> i = FibIter(100) >>> i.i = 10 >>> list(i) [1, 11, 12, 23, 35, 58, 93] |