Machine Morning

機械学習やWebについて学んだことを記録しています。

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__()を呼び出すことはできない。