バリケンのPython日記 RSSフィード

2008-12-12

[] イテレータとジェネレータ(4)  イテレータとジェネレータ(4) - バリケンのPython日記 を含むブックマーク はてなブックマーク -  イテレータとジェネレータ(4) - バリケンのPython日記  イテレータとジェネレータ(4) - バリケンのPython日記 のブックマークコメント

この間の続きだよ。

じゃあ、前回の予告どおり今回はジェネレータを作ってみよう!ジェネレータの作り方は、ジェネレータ式を使う方法とyield文を使う方法とがあるよ。

ジェネレータ式

ジェネレータ式は簡単で、リスト内包表記の角カッコを丸カッコに変えると、結果のリストではなく結果を一つずつ返すジェネレータを生成することができるよ。

>>> [x ** 3 for x in range(0, 5)]
[0, 1, 8, 27, 64]
>>> (x ** 3 for x in range(0, 5))
<generator object at 0x00DBF9E0>
>>> g = (x ** 3 for x in range(0, 5))
>>> g.next()
0
>>> g.next()
1
>>> g.next()
8
>>> g.next()
27
>>> g.next()
64
>>> g.next()

Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    g.next()
StopIteration
>>> 

yield文

次はyield文を使う方法だよ。関数定義中にyield文をひとつでも書くと、その関数は「ジェネレータ関数」という特殊な関数となるよ。次の例は極端な例だけど、

>>> def hoge():
	yield

	
>>> hoge()
<generator object at 0x00DC4F58>
>>>

という感じで、関数の評価結果としてジェネレータオブジェクトが返ってくることが分かるよ。

ジェネレータ関数によって生成されたジェネレータオブジェクトに対してnext()メソッドを呼ぶと、ジェネレータ関数の実行が始まるよ。そして yield文のところで関数の実行が停止して、呼び出し元に返るよ。ジェネレータはどこまで実行したかを覚えていて、再度next()メソッドを呼ぶと、次はそこから実行が再開されるよ。

これまたちょっと無理やりな例だけど、次のようにすればprint文を逐次実行することができるよ。

>>> def hoge():
	print 'aaa'
	yield
	print 'bbb'
	yield
	print 'ccc'
	yield

	
>>> g = hoge()
>>> g.next()
aaa
>>> g.next()
bbb
>>> g.next()
ccc
>>> 
トラックバック - http://python.g.hatena.ne.jp/muscovyduck/20081212