前回の記事では、Pythonにおける配列(リスト、タプル、辞書、集合)について取り扱いました。この記事ではPythonでのループ処理 forについて学習します。リストとforループはセットで使われることも多く、この2つだけでもかなりプログラミングらしくなります。
Pythonにおけるfor ループ
プログラミングではある特定の処理を何度も繰り返すという場面が非常に多くあります。この場合に使うのがforループです。例えば、科学技術計算という観点で考えてみると、次のような疑似プログラムが考えられます。(*num_stepsという変数と, solve_momentum_equationが定義されてないため、動きません)
for i in range(num_steps):
solve_momentum_equation
ここでforと書かれた部分が繰り返し処理のためのforループです。iはループ変数と呼ばれる変数でループが実行されるたびに0, 1, 2, 3, …といった具合に数値が増えていくような変数です。
次に in range()の部分ですが、この形で使われることが非常に多いのでセットで覚えてしまってもよいと思います。range関数は0, 1, 2, 3のような連続的な数値を生み出す関数です。
ここではnum_stepsという変数を引数に与えています。num_stepsは名前から分かる通り、シミュレーションのステップ数を表す変数ですので、例えば、10,000のような数値が入ります。この場合、range関数は0, 1, 2, 3, …, 9999までの10,000個の連続的な数字を生成します。
forループの最後には:(コロン)を付けます。そして、次の行ではインデントされたブロックに繰り返す処理の内容を記述します。Pythonではインデントされている事でforループの繰り返し処理の実行部分が判断されています。したがって、必ずインデントが必要です。
ここでは、運動方程式を逐次解いているという想定で、solve_momentum_equationという処理が繰り返し呼ばれる事になります。
この形がforループの一番基本的な形になりますので覚えておきましょう。
ここでは、実際に動くforループのサンプルプログラムを紹介しておきます。
x = 0
y = 0
for i in range(11):
print("current x is {x}, current y is {y}".format(x=x, y=y))
x += 1
y += x
このプログラムではxとyという変数を0で初期化し、forループで処理しています。処理の内容はxには繰り返し処理のたびに+1をし、yにはその時のxの値を積算していく処理になっています。実行結果は次の通りです。
実行結果
current x is 0, current y is 0
current x is 1, current y is 1
current x is 2, current y is 3
current x is 3, current y is 6
current x is 4, current y is 10
current x is 5, current y is 15
current x is 6, current y is 21
current x is 7, current y is 28
current x is 8, current y is 36
current x is 9, current y is 45
current x is 10, current y is 55
リストとforループの組み合わせ
最初に述べた通り、forループとリストが組み合わせて使われる事は非常に多いです。次のプログラムを見てください。
x = 0
y = 0
y_list = []
for i in range(11):
y_list.append(y)
x += 1
y += x
print(y_list)
先ほどのサンプルプログラムを少し修正したプログラムです。変更した点は、y_listという空のリストを生成し、ループ処理中のyの値をy_listに追加している点ですね。実際の科学技術計算でも同じようなプログラムを書く機会は多いと思います。例えば、forループでタイムステップを更新し、各時刻ごとの物理量(例えば、速度など)をリストに保存しておくなどの場合ですね。実行結果は次の通りです。
実行結果
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
それでは、forループのバリエーションを2つほど紹介していきます。
for + in + リスト:
先ほどまではinの次に来るのは必ずrange関数でした。しかし、実はinの次に来るのはリストでも大丈夫です。次のプログラムを見てください。
value_list = [1, 2, 3, 4, 5, 6]
for value in value_list:
print(value)
このようにinの次に来るのはrange関数である必要はなく、イテラブルなオブジェクトであればよいです。イテラブルなオブジェクトとは例えば、リストのような複数の要素から成る変数だと思えばよいです。この場合には、valueというループ変数にリストの各要素1, 2, 3, 4が順に代入されることになります。
実行結果
1
2
3
4
5
6
for + in + enumerate + リスト:
次は更に派生したenumerateについて紹介します。先ほどのリストは数値が入っていましたが、リストの中には数値が入っているとは限りません。例えば、ここでは例として文字列のリストを考えます。この場合には、今、繰り返し処理が何回目なのか?という事を知りたい場合がありますが、ループ変数には文字列が入っているので分かりません。しかし、こんなときにenumerateを使えば解決します。次のプログラムを見てください。
str_list = ["Python", "C", "C++", "Perl", "Java", "Ruby"]
for i, value in enumerate(str_list):
print(i, value)
ここでは何が起きているかを解説するより、実行結果を見た方が早いです。
実行結果
0 Python
1 C
2 C++
3 Perl
4 Java
5 Ruby
つまり、iにはループの通し番号が入り、valueには実際のstr_listの要素が入っている事が分かります。このようにenumerateを使う事で、通し番号入りのループを実行することが出来ます。結構使用頻度は高いです。
まとめ
この記事ではPythonにおける繰り返し処理 forループについて学習しました。以下で、纏めておきましょう。forループの基本形は次の通りです。
# forループの基本形
for i in イテラブルなオブジェクト:
繰り返し処理の内容
イテラブルなオブジェクトとしては、range関数やリストを使います。またforループでは:(コロン)の後に、必ずインデントを行います。そして、インデントされたブロックの中に繰り返し処理の内容を記述しましょう。
# forループの派生形
# リストを繰り返し処理する場合
value_list = [1, 2, 3, 4, 5, 6]
for value in value_list:
print(value)
# リストをループ処理する場合に数字のインデックスを得るenumerate
str_list = ["Python", "C", "C++", "Perl", "Java", "Ruby"]
for i, value in enumerate(str_list):
print(i, value)
Tips: 実はNG!?よくないforループの使い方
番外編ですが、Pythonでのforループの書き方にあまり良くない書き方があります。やや発展的なトピックスになりますので、参考程度の話です。PythonにおけるNGなforループ、それは多重forループです。次のプログラムを見てください。
nz = 100
ny = 100
nx = 100
for z in range(nz):
for y in range(ny):
for x in range(nx):
繰り返し処理
C言語やFortranでプログラムを書かれる方からすれば、一見するとよくありそうなコードです。しかし、実はこの書き方、とても実行速度が遅いです。“PureなPythonのforループはとても遅い”、この事を肝に銘じておきましょう。この為、forループを多重にする行為はNGなのです。
ではこの場合、どうすればいいのでしょう?解決策はいくつかあります。ただし、現時点でどれも紹介していない内容で、かつ少し難しいですので、頭の片隅に置いておきましょう。
- 多重forループをNumpyのベクトル演算で置き換えられないか検討する
- 関数化して、Numbaのjitデコレータを付ける
- Cupy, PyCUDAなどGPUの利用を検討する
概ねこの3つのどれかになるのではないでしょうか。もし、GPUが利用できるなら、3つ目の選択肢を取ります。どうしてもGPUが使えない場合は1つ目もしくは2つ目の選択肢を選ぶという順番になろうかと思います。ここではレベル的に高度になりますので詳細は割愛しますが、Pythonでは多重forループはなるべく書かない、この事を意識してプログラミングをしましょう。
最新記事 by t-tetsuya (全て見る)
- 【GPyOpt】Python x ベイズ最適化の基本をマスターしよう - 2020年12月29日
- Python print関数の基本の使い方 - 2020年12月10日
- Python関数の書き方の基本 - 2020年12月1日
・forループのいくつかのバリエーション
・Pythonで陥りやすいNGなforループ
について理解することができます。