データ処理においては,同じ処理を何度も繰り返すことがよくあります. また一般にデータを処理する過程では,データ次第で適用する処理を変えることもよくあります.
ここでは同じ処理を指定された回数だけ繰り返す方法,また条件によって異なる処理を実行する方法について説明します.
もくじ
例題1
ここで二つのプログラムを示します.
繰り返し処理
ここでは指定された回数だけ処理を繰り返す仕組みについて説明します. なお繰り返し処理としては,より一般的には「条件次第で処理を繰り返すかどうかを決める」仕組みが利用できますが,ここでは扱わないことにします.
例題1の1番目のプログラム(polygons0.py)では,亀の動作を一つ一つすべて書き下しています. そのため,正方形,正五角形,正八角形,正十二角形と,頂点と辺の数が増えるほど,プログラムの記述が長くなっています. さらに頂点・辺の数が多い正多角形を描くことを考えると,そのようにプログラムを記述することは現実的ではないことに気づきます.
これらの図形を描く過程では同じ処理が繰り返されていることが明らかです. 実際,たとえば一辺がrの正方形を描画する方法は「r進んで90度回転することを4回繰り返す」と説明できます. プログラムにおいても,まさにこのように処理の繰り返しを明示的に表現することができます. 上に示した2番目のプログラム(polygons1.py)では, Pythonの繰り返しのための基本的な方法としてfor文を使っています.
r = 100 for i in range(4): forward(r) turn(90)
for文ではrangeで回数を指定して, 続くブロック(forから1段インデントを深くした一連の行)の処理を 指定した回数だけ繰り返すことができます.
この例の場合,処理を4回繰り返します. また1回目,2回目と4回繰り返す間にi=0,1,2,3と順に iに値が代入されます(この例では繰り返しにおいてiの値は使っていません).
よく使われるfor文は次のような構造になっています.
for 変数 in シークエンス: 繰り返し処理するブロック
ここでの「シークエンス」とは繰り返しのときに「変数」に順に代入されるデータの列(sequence)です. nを正の整数としてrange(n)は「0,1,2,...,n-1」というシークエンスに相当するものです. 他にもさまざまなシークエンスがあります(rangeにもバリエーションがあります).
さて繰り返し回数は整数値だけでなく,変数を使った式で定めることもできます.
n = 10 # (a) n(=10)回処理を繰り返す for i in range(n): : : # (b) n-1(=9)回処理を繰り返す for i in range(n-1): : :
プログラムの処理が進んでいく過程を流れとしてとらえると, 繰り返し処理ではプログラムの一部を何度も通っていくことになります. このことから繰り返し処理をループとも呼びます.
for文での繰り返しで「for」の直後に指定する変数(上の例ではi)を「ループ変数」と呼んだりします. 上のようなシークエンスに対するfor文では, ループ変数には,ブロックの処理を1回繰り返すたびにシークエンスのデータが前から順に代入されていきます. 上の例では,ループ変数が何のために指定されているのか分からないかと思います. ループ変数の使い方については,後述します.
繰り返しの繰り返し
繰り返す処理として繰り返し処理を実行することもできます. つまり繰り返しを繰り返すわけです. 繰り返しの繰り返しを二重ループといいます. たとえば表計算のように縦横に並んでいるデータを処理するには二重ループを用いるのが自然です.
次に三角形を5つ描くプログラム(five_triangles.py)の一部を示します.
for j in range(5): # 正三角形を描く for i in range(3): forward(s) turn(120) turn(72) # 次の三角形に向きを合わせる
全体は5回の繰り返し処理で,繰り返しのたびに『3回の繰り返しによって正三角形を描く』処理と『72度向きを変える』処理を実行しています.
パターンの繰り返し
ループでは完全に同一の結果が得られる処理を繰り返すだけとは限りません. たとえば,ループ内で変数の値を変えていくことで, 変化をともないながら,一定のパターンで結果が変わっていく処理を繰り返すこともできます.
次にだんだん大きくなる三角形の列を描くプログラム(triangle_sequence.py)の一部を示します.
n = int(askv("何個描きますか?")) s = 30 ds = 10 : : for j in range(n): # 正三角形を描く begin_fill() for i in range(3): forward(s) turn(120) end_fill() s = s + ds # sをdsだけ増やす begin_hover(); forward(s); end_hover()
ループ内で毎回sにdsを加えるようにしているため(s = s + ds),処理を繰り返すたびに描かれる三角形の一辺の長さsがdsずつ長くなります.
ループ変数の利用
ここまで見てきたfor文では「for」の直後に「ループ変数」を指定しています. for文では,しばしばループ変数の値をループ内で利用します. 例として,さきほどのプログラム(triangle_sequence.py)を拡張して三角形の色を変えるようにしたプログラム(triangle_sequence2.py)の一部を示します.
n = int(askv("何個描きますか?")) s = 30 ds = 10 : : for j in range(n): # 正三角形を描く g = int(j*100//n) color(12,g,65) begin_fill() for i in range(3): forward(s) turn(120) end_fill() s = s + ds # sをdsだけ増やす begin_hover(); forward(s); end_hover()
上で示したプログラムではループ変数に値を代入する式は記述されていませんが, まず外側のjについてのfor文では,繰り返しの間に「j=0」から始まって,処理がループの先頭に戻るたびに,自動的にjが1ずつ増えるようになっています. 具体的には,初回のループではj=0で処理が行われて,j=1,2,...と進んで,最後にj=n-1での処理を行った後,ループが終了します(1回めがj=0から開始されるとn回めはj=n-1になります).
内側のiに関するfor文は,外側のjに関するループのj=0,1,...,n-1のそれぞれについて,実行されます. つまり内側のiに関するfor文はn回実行されます. そのn回のそれぞれにおいて, 毎回「i=0」から始まって, 処理がループの先頭に戻るたびに,自動的にiが1ずつ増えるようになっています. 内側のfor文の繰り返し回数は3ですので,i=0,1,2について処理が行われます. プログラムの全体としてはi=0,1,2での処理がn回繰り返されることになります.
ループ変数に関する注意
ループ変数の使い方には注意が必要です. 次のプログラム(unit_row.py)を見てください.
# j = 0,1,2,3のそれぞれについて, # 1行に「unit」を(2j+1)個並べて表示する unit = "*" # 表示する記号unit k = 0 # 変数kを定義 print(f"initial value: k == {k}") for j in range(4): # j = 0,1,2,3 # unitを2j+1個並べて表示(k=0,1,..,2jについてunitを表示) for k in range(2*j+1): print(unit,end="") # 最後に改行しない print(f" {2*j+1}") # kの値を調べる print(f"final value: k == {k}")
このプログラム(unit_row.py)をダウンロードして実行してみると,次のように表示されます.
initial value: k == 0 * 1 *** 3 ***** 5 ******* 7 final value: k == 6
この結果に示されている通り,変数kの値は,最初は0で, プログラムの最後では6になります. 0ではありません.
for文をよく見ると,内側のfor文のループ変数として「k」を使っています. この「k」は最初の「k」と同じ変数です. 外側のfor文はj=0,1,2,3について実行されて, 最後の「j=3」のとき,内側のfor文はk=0,1,2,...,6について実行されます(j=3のとき,2j+1=7). ループ変数kにはこのように0,1,2,...,6が順に代入されますので, for文を終了した後には「k=6」となるわけです.
この例のように,ループ変数を不用意に決めると,一見よく分からない状況に陥る危険性があります. ループ変数を特定の名前にする必要はありませんので,このような場合には,他の処理に影響しないように変数名を変更すれば,問題は起きなくなります.
とくに上のプログラムの場合は,内側のfor文ではループ変数kを使っていません. つまりループ変数kは何も仕事をしていません. しかしfor文ではループ変数を省略することはできません. このような場合,Pythonでは習慣的に'_'(アンダースコア1文字)という名前の変数を用います. データ処理に使う変数には'_'という意味のない名前は使わないでしょうから, その場での使い捨ての変数として'_'を使うわけです.
# ループ変数に'_'を使う例 # (for文ではループ変数を使っていない) for _ in range(3): print("Hello, World!")
例題2
- 番号が10で割りきれるときは赤
- それ以外で番号が5で割りきれるときは青
- どちらにも当てはまらない番号では緑
次にプログラムを示します.
条件分岐
例題2のプログラムにおいては,描く円が何番目か次第で色を変えることになります. 一般にさまざまな問題で条件次第で異なる処理を行う必要があります. 条件次第で異なる処理を行うことを条件分岐と呼びます. ここでは条件分岐を実現する仕組みについて説明します.
if文
Pythonには条件分岐の仕組みとしてif文が用意されています. ここではまずif文の構造を説明します. また条件を表現する式については,「条件式」の節で説明します.
もっとも単純なif文は次のような構造になっています.if 条件式: 「条件式」が真であるときに実行するブロック(if節)

ifに続いて判断すべき条件を表す式,つまり条件式を記述します. プログラム実行時には条件式が正しいのか(真),正しくないのか(偽)が判断されます. 条件が正しい場合にのみ,「if 条件式」の後のブロックが実行されます. この部分をif節といいます. 条件が正しくない場合には,if節は実行しないで先に進みます.
条件が正しくない場合にも処理を実行する場合にはifの後にelseを入れます.
if 条件式: 「条件式」が真であるときに実行するブロック(if節) else: 「条件式」が偽であるときに実行するブロック(else節)

if〜elseの部分がif節となり,条件が正しいときのみ実行されます. else〜endの部分は条件が正しくないときのみに実行されます. 後半の部分をelse節といいます.
さてここまで見たif文は2択で処理を選ぶ仕組みになっています. 3択以上で処理を分けるには複数の条件を組み合わせます. そのような場合は,二つめ以降の条件式は,elifにつづいて記述します.
if 条件式1: 「条件式1」が真であるときに実行する部分(if節) elif 条件式2: 「条件式1」が偽であり「条件式2」が真のときに実行する部分(elif節) else: 「条件式1」が偽であり「条件式2」も偽のときに実行する部分(else節)

if〜elifがif節であり,ifにつづく条件式1が正しいときのみ実行されます. elif〜elseがelif節であり, ifにつづく条件式1が正しくなく,elifにつづく条件式2が正しいときのみ実行されます. else以降がelse節であり,条件式1も条件式2も正しくないときにのみ実行されます.
elif節は必要に応じていくつでも並べることができます. else節は必要であれば最後に一つだけ作ることができます.
一般にif文ではif(1個),elif(0個以上)で指定されている条件式を上から順に評価していって, 条件が成り立つものが出現した場合は対応する節を評価して,その時点でif文の処理を終了して次に進みます. 一方if,elifで指定されている条件式がどれも正しくないとき, 最後にelse節があれば,その内容が実行されます. else節がなければ何も実行されないことになります. なお最初に取り上げたように(ifのみ,ifとelseのみ),elif節,else節は不要であれば省略できます.
節(if節,elif節,else節)の中には任意の式を書くことができます. すなわち節の中にまたif文を書くこともできます. これにより,より複雑な条件判断に基づくプログラムを記述することができます.
例題2のプログラム(dots.py)では,次のようにして,描画する円の色を決めています.
# 円の番号(j)次第で色を決める if j % 10 == 0: # jを10で割った余りが0 color(97,6,25) elif j % 5 == 0: # jを(10で割った余りが0でなくて)5で割った余りが0 color(0,25,75) else: # それ以外の場合 color(25,62,25)
また最初に描画する円の個数として適切な値が指定されているかどうかをチェックしています.
n = int(askv("何個描きますか?"))
if n < 1:
return # ここで処理をやめる
描く円の個数nが1未満では不適切です. そのような場合,このプログラムでは,それ以上,先には進まずに描画処理を終えるようになっています. なおこのようにプログラムの処理でデータが想定通りかどうか確認して,そうでない場合に実行する特別な処理を例外処理といいます.
条件式
if文では条件を表す式(条件式)を利用します. 条件式を評価した結果は「真」(正しい)か「偽」(正しくない)のどちらかに判定されます. ここではよく利用される条件判断のための演算子を紹介します.
比較演算子
条件式では二つのデータの大小関係を調べる演算がしばしば使われます. 大小比較の演算子には,次のようなものがあります.
x < y | xはyより小さい |
x <= y | xはyより小さい,あるいは等しい |
x == y | xとyは等しい |
x >= y | xはyより大きい,あるいは等しい |
x > y | xはyより大きい |
x != y | xとyは等しくない |
「==」と「=」
「等しい」は「==」(等号二つ)と書くことに注意してください. 「=」(等号)は代入と解釈されます.
Pythonでの「真」と「偽」
Pythonには真偽を表す値として「True」と「False」が定義されています. 条件式としては評価した結果が「True」か「False」となる式を使うのが一般的です.
x = 1 if x > 0: # x > 0 → True print("positive") elif x < 0: print("negative") else: print("zero") # ==> positiveと表示される
Pythonでは「True」「False」だけでなく, すべての値について,それが「真」であるか「偽」であるかが決められています.
具体的には「偽」と判断されるデータが定義されていて, それ以外はすべて「真」と判定されます. 次に「偽」と判定されるデータを示します.
False # 真偽値の「偽」 None # 値がないことを意味するデータ 0 # 整数値の0 0.0 # 小数値の0 '' # 空の文字列 [] # 空のリスト () # 空のタプル {} # 空の辞書
たとえば次のようなプログラムも問題なく動作します.
x = 0 if x: # x → 「偽」 print("true") else: print("false") # ==> falseと表示される
論理演算子
複数の条件を一つの式に組み合わせたい場合があります. そのようなときには,論理演算子を用います.
条件A and 条件B | 条件Aと条件Bがともに成立するときに真となる |
条件A or 条件B | 条件Aまたは条件Bの少なくともどちらかが成立するときに真となる |
not 条件A | 条件Aではないときに真となる |
サンプルプログラム
サンプルプログラムを示します.