< 前の記事 | | | Web講座TOP | | | 次の記事 > |
初心者向け Python講座 - 第9回「プログラムの繰り返し」
投稿者:3G 大毛
今回は for 文と while 文によるプログラムの繰り返し(ループ)を勉強します。for 文の方はあらかじめ繰り返しの回数が分かっていないと使えませんが、while 文はそうでなくても使えます。一見、while 文の方が便利に見えますが、できるだけ for 文を使うことをおすすめします。というのも、while 文は無限ループしてコンピュータが動かなくなってしまう危険性があるからです。

for 文
「プログラム A を3回繰り返せ」のようなプログラムを書くには for と range 関数を使って次のように書きます:
for i in range(3): A
ここで、for の後の「i」は繰り返しの回数を表す変数で、「i」でなくとも好きな名前にできます。変数 i は A の中でint型の整数として使うことができます。「in range(3)」と指定すると、i は繰り返しごとに 0, 1, 2 と 1 ずつ増えます。(「3」と指定するとその手前の「2」までになるので注意します。)
for から A までの部分をまとめてfor 文といいます。if 文の時と同じように A にはインデントをつけます。具体例を見ていきましょう。まずは変数 i の動作を知るために、このように print関数で繰り返しごとに i を表示してみましょう:
for i in range(3): print(i)
繰り返しは合計3回行われていて、i は0から2まで1ずつ増えていることがわかりました。
次に、実用的な例を考えてみましょう。いま、いくつかの数を要素として持つリスト A があるとします。A の要素の平均値を求めてみます。平均値は、各要素の合計値を要素の個数で割ると求まります。例えば、A = [3,1,4,0,2] のとき、各要素の合計値は 3+1+4+0+2=10 で、要素の個数は 5 ですから、平均値は 10÷5=2.0 となります。
A = [3,1,4,0,2] n = len(A) s = 0 for i in range(n): s = s + A[i] print(s/n)
このプログラムでは、変数 n は A の長さ、つまり整数の 5 を表します。変数 s は合計値の計算の途中結果を表すために使います。はじめは何も足していませんから s の初期値は 0 とします。for 文では「in range(n)」としたので「in range(5)」と同じことになり、i は0から4まで動きます。
for 文の繰り返しの中では「 s = s + A[i] 」 として A の i 番目の要素を全て足していきます。左辺の s と右辺の s は同じではありませんので注意しましょう。右辺の s は古いもの、左辺の s は新しいものです。
(分かりにくい人は i を 0 から順に動かしていって動作を確認しましょう。最初は「s=0」です。i=0 の回で「 s = s + A[i] 」は「 s = 0 + A[0] 」、つまり「 s = A[0] 」と同じです。i=1 の回で「 s = s + A[i] 」は「 s = A[0] + A[1] 」となります。)
for 文が終わると s は合計値を表しているので、n で割ったもの s/n が求める平均値です。
正しい平均値 2.0 が得られました。
break 文
break 文を使うと、繰り返しを途中で止めることができます。最初の例のようにprint関数を3回繰り返すプログラムを考えます。break 文を使って3回目の print(i) の手前で中断するには次のようにします:
for i in range(3): if i==2: break print(i)
本来 0, 1, 2 と表示されるところが、今回は 0, 1 で止まりました。
※ if 文に対しては、break 文は何もしません。
continue 文
continue 文を使うと、繰り返しをスキップすることができます。continue 文を使って2回目の print(i) をスキップするには次のようにします:
for i in range(3): if i==1: continue print(i)
本来 0, 1, 2 と表示されるところが、今回は 0, 2 となりました。
※ if 文に対しては、continue 文は何もしません。
for 文の入れ子
for 文の中に for 文が入ることはよくあります。次の例で動作を確認してみましょう:
for i in range(3): print('i=', end='') print(i) for j in range(4): print(j)
i のループでは i の値を「 i= 」と書いた後に表示し、 j のループでは単に j の値を表示するようにしてみました。
for 文の入れ子のことを多重ループといいます。多重ループで break 文や continue 文を使うと一番内側のループにだけ効果があります。試してみましょう:
for i in range(3): print('i=', end='') print(i) for j in range(4): if j==1: continue elif j==3: break print(j)
break 文と continue 文は内側の j のループには効果がありますが、外側の i のループには効果がありません。
それぞれの j のループで j==1 がスキップされ、j==3 で中断されています。
while 文
プログラムを繰り返したいときに、何回繰り返すか事前に分からない場合は for 文ではなく while 文を使います。「条件 A が成り立つ限りずっとプログラム B を繰り返せ」のようなプログラムを書くには while を使って次のように書きます:
while A: B
while から B までの部分をまとめて while 文といいます。if 文や for 文の時と同じように B にはインデントをつけます。A には True か False を表す式を書きます。while 文は毎回この式を元に繰り返しをするかどうか判断します。実用的な例を見てみましょう:
while input('何かご用ですか?')!='exit': print("終了するには'exit'と入力してください。")
このプログラムは繰り返しのたびに「何かご用ですか?」と表示し、入力エリアが出てきます。入力された文字列が’exit’でないときは print 関数が実行されて while 文が繰り返されます。’exit’のときは while 文から抜け出し、プログラムは終了します。
while 文でも break 文や continue 文が使えます。条件をあえて「True」にして無限ループとし、break 文を使って脱出するということがよくあります:
while True: s = input('何かご用ですか?') if s=='exit': break print("終了するには'exit'と入力してください。")
このプログラムは先ほどのものとまったく同じ動作をします。
range 型(中級者向け)
今まで for 文に range関数というものを使ってきました。range関数が返すものは range 型のデータで、整数の範囲と「ステップ」の情報を持っています。ステップについては後で説明します。まずは、型を確認してみましょう:
print(type(range(10)))
range関数はrange型のデータを作ることが分かりました。
「 range(10) 」のように、range関数に1つの数を与えると、range型の表す範囲の始点は 0 で終点はその数になります。ただし「終点」は、第6回で勉強したリストの「スライス」と同じように「未満」を表します。つまり、range(10) は 0 から 9 までの整数の範囲を表します。list型に変換して確認してみましょう:
list(range(10))
range(10) はリストで言うと [0,1,2,3,4,5,6,7,8,9] に対応することがわかりました。range型がリストと違うのは、実際に途中の整数を表すデータが作られているわけではないということです。例えば range(100000000) と書いても実際に1億個の整数のデータがコンピュータ上に作られるわけではないので安心してください。
「 range(1,10) 」のように、range関数に2つの数を与えると、始点は1番目に与えた数で終点は2番目に与えた数になります。
list(range(1,10))
「 range(1,10,2) 」のように、range関数に3つの数を与えると、始点は1番目に与えた数で終点は2番目に与えた数になり、そして3番目に与えた数ごとに増えていきます。3番目に与えた数をステップといいます。指定しないとステップは1になります。ステップが2なら1個飛びになります。
list(range(1,10,2))
「 range(10,1,-1) 」のように、ステップに負の数を与えると逆順になります。ステップが -2 なら逆順で1個飛びになります。
list(range(10,1,-1))
「 range(10,1) 」や「 range(1,10,-1) 」のように、始点と終点が逆のときは空のリストと同じになります。
list(range(1,10,-1))
イテラブル型(上級者向け)
実は for 文の「 in 」の後には、range型以外にも、リストや文字列、タプル、辞書などを置くことができます。正確には iterableと呼ばれる種類のデータ型を置くことができます。イテラブル型は、「要素」とよばれるものを持っていて、一個一個順番に要素を取り出せるデータ型です。for 文でイテラブル型を使うと、繰り返しごとに要素が一個一個取り出されて、指定した変数にバインドされます。
イテラブル型かどうかを判定する良い方法は、list関数を使ってリストに変換してみることです。そうすれば、イテラブル型としての要素とその順番が分かります。エラーが出てリストに変換できなければイテラブルではありません。range関数やリスト、タプルについてはもう説明の必要はないでしょう。文字列をリストに変換してみます:
list('Tokyo')
文字列をイテラブル型として考えると、要素は各文字で、順番は先頭からになることが分かりました。今度は辞書をリストに変換してみます:
list( {'a':10, 'b':11, 'c':12} )
辞書をイテラブル型として考えると、要素は各キーとなることが分かりました。キーの順番は特に決まっていないと考えてください。(最近のバージョンのPythonでは追加した順になることが保証されるようになりました。)
enumerate 関数(上級者向け)
for 文の「 in 」の後に書くイテラブルとしてrange型以外を使うときは、各繰り返しが何回目であるかと言う情報が失われてしまいます。(この講座では for 文はrange関数とセットで使うことを基本としますが、これがその理由になります。)そこでPythonでは各要素に、繰り返し回数の情報をセットにして、それを新たな要素としてfor 文に渡すイテラブルが用意されています。それがenumerate関数になります。
具体例を見てみましょう。「 'Tokyo' 」という文字列を for 文のイテラブルとして使うと次のようになります:
for c in 'Tokyo': print(c)
変数 c の内容は文字列「 'Tokyo' 」に現れる文字の1つ1つになります。しかし、これでは今何回目の繰り返しなのかが分からないので不便です。enumerate関数を使うと次のようになります:
for i, c in enumerate('Tokyo'): print(i, end=':') print(c)
enumerate関数を使うときは、for の後に2つの変数を指定します。1番目の変数には繰り返し回数を表す整数がバインドされます。2番目の変数には文字列の各文字がバインドされます。
enumerate関数を使わずに同じ動作のコードを書くのは、いつでも簡単にできます。先ほどの例をrange関数を使って書き換えて見ましょう:
A='Tokyo' for i in range(len(A)): print(i, end=':') print(A[i])
Python では enumerate 関数を使った for 文の書き方を「Pythonic」(Pythonらしい)といって推奨しています。しかしながら、従来の書き方と本質的な違いはなく、少なくとも初心者は enumerate 関数を使う必要はないと思います。

練習問題
次のうち好きなプログラムを作ってみてください:
(1) for 文を使って、2を100回かけた数(つまり2の100乗)を計算するプログラム
(2) リストA = [3,1,4,0,2] を逆順にしたリスト B = [2,0,4,1,3] を作るプログラム
(3)(中級者向け)リストA = [3,1,4,0,2] を要素を大きい順に並び替えたリスト B = [4,3,2,1,0] を作るプログラム
◇ (1)の解答例 ◇ (※クリックして展開して下さい)
a = 1 for i in range(100): a = a*2 print(a)
◇ (2)の解答例 ◇ (※クリックして展開して下さい)
A = [3,1,4,0,2] B = [] m = len(A) for i in range(m): B.insert(0,A[i]) print(B)
(別解)
A = [3,1,4,0,2] B = [] m = len(A) for i in range(m): B.append(A[m-1-i]) print(B)
◇ (3)の解答例 ◇ (※クリックして展開して下さい)
A = [3,1,4,0,2] B = [] m = len(A) for i in range(m): n = len(B) if n==0: B.append(A[i]) else: for j in range(n): if A[i]>=B[j]: B.insert(j, A[i]) break elif j==n-1: B.append(A[i]) print(B)
< 前の記事 | | | Web講座TOP | | | 次の記事 > |