この記事で分かること
- Pythonのyield文とは何かが分かる
- Pythonのyield文の使い方が分かる
Pythonのyieldをfor文で使う方法の概要
この記事では、Pythonの「yield」文の使い方を解説します。「yield」を使う場合には、合わせて「for」文を使うことが多いですが、そのようなオーソドックスな「yield」文を使った例を説明します。
その後、「yield」がどのように動作するのかを把握する為に、「yield」を含む関数の戻りのタイプと、そのタイプの使い方をサンプルプログラムを見ながら説明します。
この記事では、Pythonの「yield」文の使い方を解説します。「yield」を使う場合には、合わせて「for」文を使うことが多いですが、そのようなオーソドックスな「yield」文を使った例を説明します。
その後、「yield」がどのように動作するのかを把握する為に、「yield」を含む関数の戻りのタイプと、そのタイプの使い方をサンプルプログラムを見ながら説明します。
Pythonのyieldをfor文で使う方法の前提環境
Pythonの「yield」の使い方の前提の環境は、下の記事で説明している私の環境と同じ環境で確認しています。
また、レンタルサーバなどのLinuxサーバを使っている場合は、下の記事でプログラミングする環境の作り方を説明しています。もし、まだプログラムする環境ができていない方は、先にこちらの記事を読んで、プログラミングできる環境をつくることをおすすめします。
Pythonのyieldをfor文で使うサンプルプログラム
サンプルプログラムでは、「yield」の動作を確認するために、「For文を使った例」と「For文を使わない例」の2つのプログラムを説明します。
yieldの使い方のサンプルコード(for文を使った例)
ここでは、yieldの動作を確認する為に、8と2の四則演算の結果をyieldで返す関数 「test_yield」を次のサンプルプログラムのように定義します。
def test_yield():
a = 8
b = 2
yield a+b
yield a-b
yield a*b
yield a/b
- 「test_yield」を宣言する
- 変数「a」を8で初期化する
- 変数「b」を2で初期化する
- 変数「a」と変数「b」を足した結果をyieldで返す
- 変数「a」と変数「b」を引いた結果をyieldで返す
- 変数「a」と変数「b」を掛けた結果をyieldで返す
- 変数「a」と変数「b」を割った結果をyieldで返す
「yield」 文で書かれた関数を呼び出すと、その関数の返り値としては、 generator(ジェネレータ)という種類の戻りが返却されます。For文の1回目のループでは1つ目の「yield」に指定されている値が返却され、次の2回目のループでは、2つ目の 「yield」で指定されている値が返却されいく。という具合に処理されます。
なので、戻りが「yield」で指定されている関数呼び出し側でFor文を使う理由は、複数回に渡って戻り値を戻すという正確があるからです。
「yield」で複数の戻り値が返却されているかを確認する為に、下のMainの処理では、関数「test_yield」の戻りのタイプの表示と、関数「test_yield」の戻りをFor文で要素を1つずつ表示しています。
if __name__ == '__main__':
print(type(test_yield()))
for ele in test_yield():
print(ele)
- 関数「test_yield」の戻りの型を表示する。
- 関数「test_yield」で得た値を変数「ele」に代入しながら、for文で「ele」を表示する。
結果は、下のようになり、関数 __test_yield__ の戻りのタイプは「generator」となっており、8と2の足し算、引き算、掛け算、割り算の結果がそれぞれ表示されています。
$ python test.py
<type 'generator'>
10
6
16
4
yieldの使い方のサンプルコード(for文を使わない例)
次は、For文を使わない例を考えてみましょう。次のサンプルプログラムように、関数「test_yield」の戻りを一旦 「gen」という変数に入れます。その後、generator変数の関数「next()」を呼び出して、中断していた「test_yield」の処理を再開します。逐次yieldされた値をprint文で表示します。
if __name__ == '__main__':
print(type(test_yield()))
gen = test_yield()
print(gen.next())
print(gen.next())
print(gen.next())
print(gen.next())
- 関数「test_yield」の戻りの型を表示する。
- 関数「test_yield」で得たgenerator変数「gen」に代入する
- next()関数を使って変数「gen」の次の項目を表示する
- next()関数を使って変数「gen」の次の項目を表示する
- next()関数を使って変数「gen」の次の項目を表示する
次の結果のように、関数「test_yield」から返却されたジェネレータ(ここでは変数gen)のメンバ関数である「next」を呼ぶと、次のyield までの処理を実行し、値を返します。もう一度「next」を呼ぶと、次の「yield」で指定される値を返してくれることがわかります。
$ python test.py
<type 'generator'>
10
6
16
4
下のサンプルプログラムのように、関数「test_yield」の中で定義されている「yield」の数以上にnextを呼び出してみましょう。関数「test_yield」の中では、4つの「yield」で指定された処理がありましたが、ここでは5回「next」を呼び出しています。
if __name__ == '__main__':
print(type(test_yield()))
gen = test_yield()
print(gen.next())
print(gen.next())
print(gen.next())
print(gen.next())
print(gen.next())
- 関数「test_yield」の戻りの型を表示する。
- 関数「test_yield」で得たgenerator変数「gen」に代入する
- next()関数を使って変数「gen」の次の項目を表示する
- next()関数を使って変数「gen」の次の項目を表示する
- next()関数を使って変数「gen」の次の項目を表示する
- next()関数を使って変数「gen」の次の項目を表示する
- next()関数を使って変数「gen」の次の項目を表示する
下の実行結果表示のように、「yield」の数以上に「next」を呼び出すとエラーになってしまいます。
$ python test.py
<type 'generator'>
10
6
16
4
Traceback (most recent call last):
File "test.py", line 23, in <module>
print(gen.next())
StopIteration