yieldとは
yieldを理解するために、まずはIterablesについて解説する。
Iterables
listを作成すると要素を一つずつ読むことができる。この要素を一つずつ読み出す作業をiterationと呼ぶ。
>>> sample_list = [1, 2, 3] >>> for i in sample_list: ... print(i) 1 2 3
sample_listはiterableである。またリスト内包表記によってもlist、すなわちiterableなオブジェクトを作成できる。
>>> sample_list = [x*x for x in range(3)] >>> for i in sample_list: ... print(i) 0 1 4
listに限らずstringやファイルなど、for文によって一つずつ要素を読むことができるものはすべてiterableである。
Generators
Generatorは一度しかiterateすることができないiteratorである。Generatorはlistなどのiteratorと違い、要素のすべての値をメモリに保存することはない。
>>> sample_generator = (x*x for x in range(3)) >>> for i in sample_generator: ... print(i) ... 0 1 4
一回目はfor文でiterateすることができた。続いてsample_generatorがfor文によって二回目のiterate実行可能か確認する。
>>> for i in generator: ... print(i) ...
Yield
yieldはgeneratorを返すreturnのようなものである
>>> def createGenerator(): ... sample_list = range(3) ... for i in sample_list: ... yield i*i ... >>> sample_generator = createGenerator() >>> print(sample_generator) <generator object createGenerator at 0x1019666d8>
この時点ではgeneratorオブジェクトが返ってくるだけで、iterateしていないので要素は取得できない。
generatorオブジェクトをitereteして要素を取得するには、Python3系では__next__()
を用いる。createGeneratorで定義したgeneratorでは3回要素をgenerateするので3回iterateできるだろう。実際に確認してみよう。
>>> sample_generator.__next__() 0
一回目のiterateにより1つ目の要素がgenerateされた。 連続してiterateを繰り返してみる。
>>> sample_generator.__next__() 1 >>> sample_generator.__next__() 4 >>> sample_generator.__next__() Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
3回目のiterateで要素がgenerateされたが、4回目のiterateをしてみると、エラーが返ってきた。生成する要素の回数しか__next__()
を呼び出すことはできない。