イテレータとジェネレータ式(おまけでジェネレータも)

イテレータとジェネレータ式って同じことできるよなー、と思いつつ、実験を行ってみた。
確かに出力結果は同じものを得られたが、内部的にはオブジェクトの扱いが異なるようだったので残しておく。

イテレータで書いた場合

まぁ、あたりまえの動き。

>>> i = iter("abc")
>>> i.next()
'a'
>>> i.next()
'b'
>>> i.next()
'c'
>>> i.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> print i
<iterator object at 0xb74a2f4c>

ジェネレータ式で書いた場合

ジェネレータ式は、無名のジェネレータ(と理解している)で、書き方は、リスト内包表記の四角括弧[]を丸括弧()で書くような感じ。(下例参照)

>>> g = ( st for st in "abc" )
>>> g.next()
'a'
>>> g.next()
'b'
>>> g.next()
'c'
>>> g.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> print g
<generator object <genexpr> at 0xb781211c>

注目したいのはイテレータ、ジェネレータ式の最後でprint iやprint gした部分。
中身はそれぞれiteratorとgeneratorになっていて、異なるオブジェクトタイプであることが分かる。

ジェネレータで書いた場合

さらに、ジェネレータについても記載しておく。
正確には、ジェネレータ式もジェネレータもどちらもジェネレータオブジェクトを扱う操作なので、無名なオブジェクトか、関数オブジェクトかどうかの違いでしかないが。(きっと)

>>> def gen(charas):
...     for chara in charas:
...             yield chara
... 
>>> 
>>> g2 = gen("abc")
>>> g2.next()
'a'
>>> g2.next()
'b'
>>> g2.next()
'c'
>>> g2.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> print g2
<generator object gen at 0xb7812234>

イテレータとジェネレータ、ジェネレータ式の違い

ジェネレータはイテレータを基盤に作られているので(エキスパートPythonプログラミングp.65より)、ジェネレータで出来ることはイテレータでもできると思われる。

エキスパートPythonプログラミング

エキスパートPythonプログラミング