ジェネレータ

Pythonでジェネレータを作成するには次の2通りがある。

>>> (i for i in xrange(3))
<generator object at 0x00B34F08>
>>> def gen():
...     yield 0
...     yield 1
...     yield 2
...
>>> gen()
<generator object at 0x00BE2EB8>

つまり、リスト内包表記風(呼び方が分からない)の書き方と、関数の定義風の書き方の2通りあり、前者は、そのままでインスタンスになり、後者は関数呼び出しをするとインスタンスが生成される。


概念としては、自分の中ではジェネレータはリストと同じようなものと考えている。但し、違いはリストは全要素があらかじめ作成されるが、ジェネレータは要素を取り出すタイミングで要素が作成されるということだと思う。


何のメリットがあるのかは、難しいが、今気づいているのは以下のもの:

    • リストの要素の個数が多すぎてあらかじめ作るのがコストがかかりすぎる場合
    • 再帰処理など複雑なロジックを分かりやすく記述できる
    • クラスの代替として、状態の付いた処理をかける


リストがあらかじめ要素が作成されるのは以下のコードで確認できる。

>>> def pr():
...     print 1,
...
>>> L = [pr(), pr()]
1 1
>>> g = (pr() for i in xrange(2))
>>> g.next()
1
>>> g.next()
1

リストLを作成のタイミングで関数pr()が実行されてしまう。それに対し、ジェネレータでは要素を取り出すタイミングで要素が作成される。ジェネレータの応用方法に関しては今後の研究課題。


追記:
ジェネレータの良い表現を思いついた。"遅延評価版リスト"。Haskellの考え方も知りたいので勉強したくなった。