7. 3大構造 二. 分岐

この章では、プログラムの3大構造の2つ目「分岐(ぶんき)」を学びます。 分岐とは、「条件 に従って 処理を いくつかに 分け 、そのうちの どれか1つを実行 する」ことです。

例えば、ふだんの生活では、お酒を買う時に年齢確認が求められます。 年齢確認の後、店員が行う処理は、次のように 分岐 しています。

  • お客が20歳以上であれば、お酒を売る

  • お客が20歳以上でなければ、お酒を売らない

確認した年齢をもとに、どちらかの処理を実行しますね。

分岐は if 文(イフぶん)で実現します。 次の順番で見ていきましょう。

  1. if 文で条件を表すのに使う「比較演算子」をまず説明します。

  2. if 文について説明します。

7.1. 比較演算子

7.1.1. 処理系に数の大小を評価させる

年齢確認の例は「年齢が20歳以上と言えるか」と捉えられます。

  • 年齢が25歳のときは、20歳以上と言えます

  • 年齢が19歳のとき、20歳以上とは言えません

「年齢が20歳以上と言えるか」のような 数の大小関係 は、プログラミングして 式で表せます。 そして、プログラミング言語処理系は、その 式を評価 できます。 評価結果は、人間が大小関係を判定するときと同じ になります。

「年齢が20歳以上と言えるか」を式で表すときに使うのが 比較演算子 です。 例えば「以上」の比較演算子は >= です。

比較演算子を使った式の評価結果は、次の 2つの値のいずれか です。

比較演算子を使った式の評価結果

読み

意味

True

トゥルー

言える

False

フォールス

言えない

プログラミングでは TrueFalse のことを、「真理値(しんりち)」(または「真偽値(しんぎち)」「ブール値(ブールち)」)と呼びます。

7.1.2. 例:年齢が20歳以上と言えるか

比較演算子に慣れるため、対話モードで練習しましょう。

「年齢が20歳以上と言えるか」を式で表す練習です。 年齢を変数 nenrei で表すと、nenrei >= 20 という式で表せます。

nenrei25 を指すとき、nenrei は20歳以上でしょうか?

>>> nenrei = 25
>>> nenrei >= 20
True

25歳は20歳以上と言えますよね。 人間の判定と同じように、処理系も True と評価しました。

nenrei が指す値を 19 に変えた次の例では、20歳以上と言えるでしょうか?

>>> nenrei = 19
>>> nenrei >= 20
False

19歳は20歳以上とは言えませんね。 処理系も False と評価しました。

nenrei に代入する数値を変えて試してみてください。

if 文では、変数と比較演算子を使った式 を使って、分岐の条件を表し ます。

7.1.3. 本章で登場する比較演算子

比較演算子の中から、本章では、「以上」 >=、「より大きい」 >、「等しい」 == を使います。 主な比較演算子の一覧は、章末の発展を見てください。

繰り返しますが、比較演算子を使った式を 処理系が評価した結果は、人間が大小関係を判定した結果と一致 します。

>>> nenrei = 20
>>> nenrei > 20  # ((20は20より大きいとは言えません))
False
>>> nenrei == 20  # ((20は20と等しいと言えます))
True

7.2. if

分岐を実現する if 文の全体像は以下のようになります。

if 条件1:
    処理A
elif 条件2:
    処理B
else:
    処理C

if文も文の1種です。 関数定義と同じように、別の文を含められる文です(処理A〜Cの部分)。

年齢確認を例に、if 文を構成する要素を少しずつ紹介します。 if 文を使って、どのように処理を分岐させられるか、一歩ずつ見ていきましょう。

Atomで nenrei_kakunin.py というファイルを作ってください。

7.2.1. 単純な if 文(if のみ)

最初に if 文の 最小限の構成要素 を紹介します。 条件に従って、処理を実行する/しない と分岐します。

if 式1:  # ((ifの後に半角スペースが1つ入ります。また、コロンを忘れずに!))
    処理A(文(の並び))  # ((先頭のインデントを忘れずに!))

if で始まる行の 式1 は、分岐の条件 です。 条件には、比較演算子を使った式が使われます。

  • 式1 の評価結果が True となる(つまり、条件が成り立つ)とき、処理Aが実行されます

  • 式1 の評価結果が False となる(条件が成り立たない)とき、処理Aは実行されません

最小限の if 文を nenrei_kakunin.py に書いてみましょう。

nenrei_kakunin.py
1print("年齢確認のプログラムを開始します")
2nenrei = 25
3if nenrei >= 20:
4    print(f"{nenrei}歳はお酒が買える年齢です")
5print("プログラムを終了します")

ファイルを実行して、処理系に if 文を実行させましょう。

> python nenrei_kakunin.py

macOSでは python3 に読み替えが必要です。 詳しくは 6 章 の「はじめてのファイルを使ったプログラム」を確認してください。

入力したら Enter キーを押しましょう。

> python nenrei_kakunin.py
年齢確認のプログラムを開始します
25歳はお酒が買える年齢です
プログラムを終了します

順次により、処理系はファイルの1文目から実行します。 変数 nenrei25 を指すので、 3行目の if 文の条件 nenrei >= 20True ですね。 4行目にある print(f"{nenrei}歳はお酒が買える年齢です") が実行されました。

今度は、条件が False となる場合を見てみましょう。

nenrei_kakunin.py
1print("年齢確認のプログラムを開始します")
2nenrei = 19
3if nenrei >= 20:
4    print(f"{nenrei}歳はお酒が買える年齢です")
5print("プログラムを終了します")

ファイルの2行目で代入する値を変えました。

> python nenrei_kakunin.py
年齢確認のプログラムを開始します
プログラムを終了します

4行目の処理は実行されていませんね。

../_images/7-11_simple_if_code_flow.drawio.png

単純な if 文では、条件が True の場合のみ処理が実行される

if だけを使うと、条件が成り立つときだけ処理を実行する という分岐が作れます。

7.2.2. if ... else ...

続いて、else (エルス)を追加してみましょう。 条件が 成り立つ時の処理、成り立たない時の処理と分岐 します。

if 式1:
    処理A(文(の並び))
else:  # ((コロンを忘れずに!))
    処理C(文(の並び))  # ((先頭のインデントを忘れずに!))

処理系は、条件(式1)に従って、処理Aか処理Cを実行 します。

  • 式1 の評価結果が True のとき、処理Aが実行されます(処理Cは実行されません

  • 式1 の評価結果が False のとき、処理Cが実行されます(処理Aは実行されません

nenrei_kakunin.pyelse を追加しましょう。

nenrei_kakunin.py
1print("年齢確認のプログラムを開始します")
2nenrei = 19
3if nenrei >= 20:
4    print(f"{nenrei}歳はお酒が買える年齢です")
5else:
6    print(f"{nenrei}歳はお酒が買える年齢ではありません")
7print("プログラムを終了します")

処理系に実行させます。

> python nenrei_kakunin.py
年齢確認のプログラムを開始します
19歳はお酒が買える年齢ではありません
プログラムを終了します

nenrei >= 20False となるので、ファイルの6行目が実行されましたね! 4行目は実行されていません。

条件が True となる場合も見ておきましょう。

nenrei_kakunin.py
1print("年齢確認のプログラムを開始します")
2nenrei = 25
3if nenrei >= 20:
4    print(f"{nenrei}歳はお酒が買える年齢です")
5else:
6    print(f"{nenrei}歳はお酒が買える年齢ではありません")
7print("プログラムを終了します")

4行目が実行され、6行目は実行されません。

> python nenrei_kakunin.py
年齢確認のプログラムを開始します
25歳はお酒が買える年齢です
プログラムを終了します
../_images/7-12_if_else_code_flow.drawio.png

ifelse を使うと、条件が True の場合と False の場合とで処理が分岐する

if だけを使うと、条件が成り立つときだけの分岐でした。 ifelse を使うと、条件が成り立たない時の分岐が加わります。 ただし、条件に応じて、どちらかしか実行 されません。

[コラム] if 文で出されるエラー

if 文を書き間違えたときに、処理系が出すエラーと解決方法について知っておきましょう。

  1. ifelse の行のコロン忘れ

処理系は SyntaxError を出します。

> python nenrei_kakunin.py  # ((ifの行のコロンを忘れました))
  File "nenrei_kakunin.py", line 3
    if nenrei >= 20
                ^
SyntaxError: invalid syntax

SyntaxError を見かけたら、コロンを忘れていないか 確認しましょう。

  1. 処理の行のインデント忘れ

  2. 処理を複数行書いた時にある行だけインデントが揃っていない

(2)と(3)の場合、処理系は IndentationError を出します。 5 章関数を作って処理をまとめよう」のコラム「インデントに関するエラー」と同じです。 インデントが揃っているか 確認してください。

7.2.3. if ... elif ... else ...

elif (エルイフ)を追加すると、初めに示した構成要素が全て登場しますね。 elif新たな条件と分岐先の処理を追加 します。

if 式1:
    処理A(文(の並び))
elif 式2:  # ((elifの後の半角スペースが1つ入ります。また、コロンを忘れずに!))
    処理B(文(の並び))  # ((先頭のインデントを忘れずに!))
else:
    処理C(文(の並び))

2つの条件(式1式2)に従って、実行される処理はA, B, Cの 3つに分かれ、どれか1つが実行され ます。

  • 式1 の評価結果が True のとき、処理Aが実行されます(処理B、Cは実行されません

  • 式1 の評価結果が False のとき、式2評価 します

    • 式2 の評価結果が True のとき、処理Bが実行されます(処理Cや処理Aは実行されません

    • 式2 の評価結果が False のとき、処理Cが実行されます(処理Bや処理Aは実行されません

nenrei_kakunin.pyelif を追加しましょう。

nenrei_kakunin.py
1print("年齢確認のプログラムを開始します")
2nenrei = 20
3if nenrei > 20:  # ((比較演算子を >= から > に変更))
4    print(f"{nenrei}歳はお酒が買える年齢です")
5elif nenrei == 20:
6    print("成人おめでとう!お酒が買える年齢です")
7else:
8    print(f"{nenrei}歳はお酒が買える年齢ではありません")
9print("プログラムを終了します")

ファイル3行目の if に続く条件 nenrei > 20False ですね。 ファイル5行目の elif に続く条件が評価されます。

ファイルを実行しましょう。

> python nenrei_kakunin.py
年齢確認のプログラムを開始します
成人おめでとう!お酒が買える年齢です
プログラムを終了します

elif の条件 nenrei == 20True ですから、6行目が実行されました。

elif とは else if の縮まった形です。 else if なので、if の条件が False の場合に 限りelif の条件が評価されます。

2行目で nenrei に代入する値を変えると、実行される処理が変わります。 書き換えて動きを確認してみてください。

if ... elif ... else ...

nenrei に代入する値

nenrei > 20 (条件1)

nenrei == 20 (条件2)

実行される処理

25

True

評価されない

4行目(25歳はお酒が買える年齢です)

19

False

False

8行目(19歳はお酒が買える年齢ではありません)

if , elif , else を使うと、

  • 条件1が成り立つ時

  • 条件1が成り立たないが、条件2が成り立つ時

  • 条件1も2も成り立たない時

と、処理が分岐するのです。

../_images/7-13_if_elif_else_code_flow.drawio.png

条件1が True の場合、条件1が False かつ条件2が True の場合、条件1が False かつ条件2 が False の場合の3つに分岐する

なお、elif を複数使って、4つ以上の分岐も表せます。

分岐はプログラムを 枝分かれ させます。 if 文でインデントされた処理それぞれは枝分かれしているように見えてきませんか。 この枝分かれのうち、実行されるのはどれか1通りだけ で、他は実行されません。

順次により、プログラムは1文目から実行されますが、文の並びに分岐を加えると枝分かれができます。 例えば、関数の処理の中に枝分かれを設けて、関数の引数に応じて実行する処理を変えることもできます。

[発展] 式 nenrei >= 20 の評価を詳しく

比較演算子と変数を使った式の評価は、a * 6 のような変数を使った式の評価(2 章)と何も変わりません。 変数がまず評価され、次に比較演算子が評価されます。

例えば、nenrei = 25 と代入したとき、 nenrei >= 2025 >= 20 を評価することになります。 25は20以上ですから、結果は True ですね。

>>> 25 >= 20
True

比較演算子も演算子ですから、変数、演算子の順 で評価されるのです。

[発展] 前提条件を満たさない時に、関数を終了する

if 文 と return を関数で組合せると、前提条件を満たさない時に、関数を終了 できます。

def souki_shuryo(nenrei):
    if nenrei < 20:  # ((nenreiは20歳以上を前提にしている))
        print("未成年なので処理を終了します")
        return
    成人の場合の処理

return 文が実行されると、関数の中の 処理の実行はそこで終わり ます。 続く行があっても実行されません。

そして、return 文は 式がなくても作用 します。

プログラマーの間では、このテクニックを「早期リターン」と呼びます。 早期リターンした後は前提条件を満たす場合の処理だけに注力できるため、プログラムが読み/書きしやすくなります。

[発展] プログラムの構造を掴む図、フローチャート

本節では、プログラムと図を左右に見比べられるように掲載しました。 これはプログラムを実行しなくても見ただけで、分岐の構造をイメージできるようになってもらいたいからです。

右側に出した図は「フローチャート」と呼ばれます。

7.3. 順次と分岐の練習(計算アプリを作る)

練習として、順次と分岐を使って簡単なプログラム(計算アプリ)を作ってみましょう。

計算アプリを実行すると、計算式が表示され、暗算した答えを入力するように求められます。 アプリは入力された答えを採点し、正解したかどうかを表示します。

これまで学んだ以下を使って計算アプリを実現できます。

  • 順次

  • 分岐(比較演算子と if 文)

  • 入力の扱い(input 関数)

新しいファイル keisan.py に作っていきましょう。

7.3.1. 例題:正解した場合だけ表示する計算アプリ

一歩一歩進めます。 まずは 正解した場合だけ「正解です!」と表示する ように作りましょう。

コマンドラインからの入力を受け取る部分は次のようになりますね。

keisan.py
1print("計算アプリです")
2nyuryoku = input("11×12は? ")  # ((入力する人が見やすいよう、末尾に半角スペースを入れています))

実行すると、コマンドラインから答えを入力できます。

> python keisan.py
計算アプリです
11×12は? 132

今の計算アプリは、何か値を入力すると終了します。 では、入力された答えが正解の場合だけ「正解です!」と表示するように処理を足してみましょう。

  • 正解がいくつか計算しましょう

  • 入力が正解と一致するかどうかで処理を分岐させるとよさそうですね

[解答] 想定解

keisan.py
1print("計算アプリです")
2nyuryoku = input("11×12は? ")
3seikai = 11 * 12
4if int(nyuryoku) == seikai:
5    print("正解です!")

4行目の if の条件で、入力と正解が一致するか比較しています。 nyuryoku数字が並んだ文字列 になっているので、整数に変えるために int(nyuryoku) とします(補足のコラム参照)。 入力と正解が一致するとき、「正解です!」と表示されます。

> python keisan.py
計算アプリです
11×12は? 132
正解です!

「正解です!」と表示する計算アプリは作れました!

[発展] 数字の入力には要注意

input 関数の返り値は、数字を入力したときも文字列 です。 対話モードで確認しましょう。

>>> nyuryoku = input("11×12は? ")  
11×12は? 132
>>> type(nyuryoku)
<class 'str'>
>>> nyuryoku
'132'

seikainyuryoku はそれぞれ数値、文字列と 型が違う ので == で比較しても 一致しません

>>> seikai = 11 * 12
>>> nyuryoku == seikai
False

入力された数字を整数として扱いたいですよね。 '132' のように 数字が並んだ文字列を整数に変換する には、int 関数を使います。

文字列を整数に変換する関数

箱の名前

int

箱は何をするか

数字の並んだ文字列を整数に変換する

箱に入れるもの

文字列(数字の並びを想定)

箱から出てくるもの

整数

>>> int("132")
132

入力された文字列を int 関数で整数に変換することで、正解と比較できるようになります。

>>> int(nyuryoku) == seikai
True

7.3.2. 練習問題1:間違えたことをフィードバックする計算アプリ

今の計算アプリは、間違えたときに何も表示されません。

> python keisan.py
計算アプリです
11×12は? 122

間違えた時に間違えた旨と正解を表示する ように変更してみましょう。

ヒント:間違えたときの分岐を追加しましょう

[解答] 正解例

正解例と完全に一致していなくても、keisan.py を実行して同じ動きをしていれば正解です。

keisan.py
1print("計算アプリです")
2nyuryoku = input("11×12は? ")
3seikai = 11 * 12
4if int(nyuryoku) == seikai:
5    print("正解です!")
6else:
7    print(f"残念>_< 正解は{seikai}でした")

入力が正解と一致しないとき が間違えたときですね。 else を使って、間違えたときの分岐を追加しました。

「間違えた旨と正解を表示」には解釈の余地があるので、表示する文章が一致していなくてもかまいません。 重要なのは、else を追加するという点です。

> python keisan.py
計算アプリです
11×12は? 122
残念>_< 正解は132でした

紙面では省略しますが、正解の場合の動作が変わっていないことも確認しましょう。

7.3.3. 練習問題2:惜しい間違いをフィードバックする計算アプリ

間違っていても、正解との差が小さい場合には、惜しい間違いと表示するようにしましょう。 正解との差が小さいというのは、入力された値と正解が1だけ違う (すなわち入力が131または133)場合とします。

入力された値と正解がいくつ違うかを計算するのには abs 関数が使えます。

絶対値を返す関数

箱の名前

abs

箱は何をするか

引数に与えた数の絶対値を返す

箱に入れるもの

整数、または浮動小数点数

箱から出てくるもの

整数、または浮動小数点数

絶対値という語が耳慣れない方は、

  • 正の数または0の場合はそのまま返し

  • 負の数の場合は、マイナスを付けて返す

と考えてください。 例えば、\(-3\)\(-(-3)\) より \(3\) を返します。

対話モードで abs 関数に慣れましょう。

>>> abs(2)
2
>>> abs(-3)
3

式を渡すことで、2つの数の差の絶対値 を求められます。

>>> abs(4 - 2)
2
>>> abs(3 - 6)
3

これを計算アプリで使いましょう。 入力された値と正解との差の絶対値が1と等しい とき、惜しい間違いと判定します。

keisan.py を変更してみてください。

ヒント:間違えたとき(入力と正解が一致しないとき)に、条件を追加します

[解答] 正解例

keisan.py
1print("計算アプリです")
2nyuryoku = input("11×12は? ")
3seikai = 11 * 12
4if int(nyuryoku) == seikai:
5    print("正解です!")
6elif abs(seikai - int(nyuryoku)) == 1:
7    print(f"惜しい!正解は{seikai}でした")
8else:
9    print(f"残念>_< 正解は{seikai}でした")

6行目に追加した elif により、seikaiint(nyuryoku) の差の絶対値が1と等しいときに、 惜しい間違いである旨が表示されます。

> python keisan.py
計算アプリです
11×12は? 133
惜しい!正解は132でした

よさそうですね! 紙面では省略しますが、正解の場合や惜しくない間違いの場合の動作に変更がないことも確認しましょう。

[発展] 主な比較演算子

主な比較演算子を紹介します。

主な比較演算子 一覧

比較演算子

比較内容

数式では

>=

以上

\(\leqq\)

<=

以下

\(\geqq\)

>

より大きい

\(>\)

<

より小さい

\(<\)

==

等しい

\(=\)

!=

等しくない

\(\neq\)

ここで初めて登場した比較演算子について、対話モードで確認しましょう。

>>> nenrei = 29
>>> nenrei <= 25  # ((29は25以下とは言えません))
False
>>> nenrei < 30  # ((29は30より小さいです))
True
>>> nenrei != 35  # ((29は35と等しくないと言えます))
True

[発展] 文字列も比較できる

数値だけでなく文字列も、比較演算子を用いて比較できます。 文字列の比較では、「等しい」 == や「等しくない」 != がよく使われます。

文字列によく使う比較演算子

比較演算子

比較内容

==

文字列どうしが一致(同じ)

!=

文字列どうしが一致しない(異なる)

>>> namae = "nikkie"
>>> namae == "nikkie"  # ((namaeが指す文字列は"nikkie"と一致しますね))
True
>>> namae != "susumuis"  # ((namaeが指す文字列は"susumuis"と一致しませんね))
True

[発展] 演算子の種類

1 章プログラムで数と文字を扱ってみよう」で +* などの演算子を紹介しました。 四則演算に使う演算子は「算術演算子」と呼ばれます。 演算子には、比較演算子、算術演算子といった種類があるのです。

[発展] 真理値に使う演算子

TrueFalse反対の関係 にあります。

  • True でない」は False

  • False でない」は True

でない」は not という演算子を使って、式で表せます。

>>> not True
False
>>> not False
True

not のように真理値に使う演算子を「ブール演算子」と呼びます。