タートルグラフィックスで学ぶ Python のキホン 第 5 章
教材コード
第 5 章

条件で分ける

「もし〜なら」.状況を見て,やることを変えさせます.

ここまでのプログラムは,書いた命令が必ず上から順にすべて実行されていました. これを順次実行といいます. 前の章,入力や乱数を使って「毎回ちがう数」を扱えるようになりましたが, 数が変わってもやることは同じでした.

今回習う条件分岐を使うと, 状況に応じて,実行する命令そのものを変えることができます. 「1 と入力されたら家を,2 なら星を描く」 「90 点以上なら『秀』と表示する」 「大吉のときだけ,お祝いの星を描く」. プログラムが,はじめて判断をするようになります.

順次実行しかできなかった機械が,ここではじめて賢く見えはじめます

この章でできるようになること
  • if の書き方(コロンと字下げ)がわかり,条件に応じた処理が書ける
  • == != < <= > >= を使って条件式が書ける
  • ==(比べる)と =(入れる)を区別できる
  • else で 2 つに,elif でいくつにも分けられる
  • andornot で条件を組み合わせられる
  • 条件を入れ子にした処理が読める・書ける
  • 変数がどこから見えるか(有効範囲)を説明でき,NameError になる場合を避けられる
  • 乱数と条件分岐を組み合わせて,おみくじやじゃんけんが作れる

5.1 もし〜なら — if

5.1.1 実行の流れを変える

次のプログラムを開いて,実行してみてください. 正三角形を描いたあと,1 辺が 100 より大きいときだけ 文字を書き足します.

if1.py
from turtle import *

length = 140          # ← ここを 60 に変えて,もう一度実行してみる

pensize(3)
pencolor("teal")

fd(length)
lt(120)
fd(length)
lt(120)
fd(length)
lt(120)

if length > 100:
    pencolor("crimson")
    pu()
    goto(length / 2, -45)
    pd()
    write("大きい三角形", align="center", font=("Arial", 20, "bold"))

ht()
done()
大きい三角形
図 5.1 length = 140 のとき.条件が成立したので文字が書かれた.

length = 140length = 60 に書き換えて, もう一度実行してください.今度は文字が出ません. 同じプログラムなのに,実行される命令が変わりました

大きい三角形
図 5.2 length = 140 → 文字が出る
図 5.3 length = 60 → 文字は出ない

5.1.2 if の書き方

if の基本形
if 条件式:
    処理

書くときの約束は 2 つだけです.どちらも忘れやすいので,声に出して覚えてください.

  1. if の行のおしまいにコロン : を打つ.
  2. 次の行から字下げ(インデント)する.半角スペース 4 つ

字下げされている行が,「条件が成立したときに実行する部分」です. 字下げをやめたところで,if の中身はおしまいになります.

どこまでが if の中身か
x = 15

if x > 10:
    print("A")       ← if の中(x > 10 のときだけ実行)
    print("B")       ← if の中
print("C")           ← if の外(いつでも実行される)
block.py
x = 15

if x > 10:
    print("A")
    print("B")
print("C")

print("----")

x = 5

if x > 10:
    print("A")
    print("B")
print("C")

上半分では A B C の 3 行,下半分では C だけが出ます. 字下げされた 2 行が,まとめて実行されたり,まとめて飛ばされたりするわけです. この「まとまり」をブロックといいます.

字下げは飾りではない Python では,字下げがブロックの範囲そのものを表します. 見やすくするための飾りではなく,文法の一部です. 第 2 章で「行の先頭の空白には意味がある」と言ったのは,このことでした.
字下げまわりのエラー
  • コロンを忘れるSyntaxError: expected ':'
  • 字下げを忘れるIndentationError: expected an indented block
  • 字下げの幅がそろっていない(3 つと 4 つが混ざるなど) → IndentationError: unexpected indent
  • タブ文字とスペースが混ざるTabError.見た目は同じでも別の文字なので厄介です.この教材のコード欄は Tab キーを押すとスペース 4 つが入ります.
何もしないブロックは書けない ブロックの中身を1 行も書かないと,これもエラーになります. 「ここでは何もしない」とわざわざ書きたいときは, pass という命令を 1 行だけ置きます.
何もしないと書く
if n == 5:
    pass                      # 5 のときは何もしない
else:
    print("5 ではありません")
もっとも,この例は if n != 5: と書けば pass は要りません. まず条件のほうを見直すのが先で, pass は形をどうしても残したいときの逃げ道だと思ってください.

5.1.3 流れ図で見る

プログラムの流れを絵にしたものを流れ図(フローチャート)といいます. ひし形が「条件を調べるところ」,四角が「処理」です. else を書かない if は,次のような流れになります.

条件式不成立成立処理
図 5.4 if だけの流れ図.成立したときだけ処理を通る.
虫食い虫食い 5-A 条件を 1 行で書く

正三角形を描いたあと,1 辺が 100 より大きいときだけ 赤い文字を書き足します.____ の行に, if の 1 行を書いてください. コロンを忘れないこと.

ヒント 書き終わったら length60 に変えて実行し, 文字が出なくなることも確かめてください.
fill1_if.py
from turtle import *

length = 150

pensize(3)
pencolor("darkcyan")

fd(length)
rt(120)
fd(length)
rt(120)
fd(length)
rt(120)

# 「もし length が 100 より大きければ」という 1 行を書く
____
    pencolor("crimson")
    pu()
    goto(length / 2, -45)
    pd()
    write("大きい", align="center", font=("Arial", 26, "bold"))

ht()
done()

5.2 くらべて True か False を出す

5.2.1 6 つの比べ方

if のうしろに書く length > 100 のような式を 条件式といいます. 2 つの値を比べる記号を比較演算子といい,全部で 6 つあります.

演算子書き方成立するのは読み方
==a == ba と b が等しいときイコールイコール
!=a != ba と b が等しくないときノットイコール
>a > ba が b より大きいとき大なり
<a < ba が b より小さいとき小なり
>=a >= ba が b 以上のとき(等しいときも成立)大なりイコール
<=a <= ba が b 以下のとき(等しいときも成立)小なりイコール
>= の順番 >==> ではありません不等号が先,イコールが後です. 数学で と書くときの順番と同じだと覚えてください.

5.2.2 条件式は TrueFalse になる

条件式は,計算されるとTrue(成立)False(不成立)のどちらかになります. この 2 つしか値をとらない型を bool(ブール)型といいます. 前の章習った intfloatstr に続く 4 つめの型です.

compare.py
x = 7

print(x == 7)      # True
print(x != 7)      # False
print(x > 10)      # False
print(x < 10)      # True
print(x >= 7)      # True
print(x <= 6)      # False

print(type(x > 10))   # <class 'bool'>

if は,このうしろの値が True なら中身を実行し, False なら飛ばします.それだけの仕組みです.

大文字・小文字に注意 TrueFalse は,先頭だけ大文字です. trueTRUE と書くと NameError になります.

5.2.3 文字列も比べられる

==!= は,数だけでなく文字列にも使えます.

strcmp.py
name = input("名前を入力してください > ")

if name == "かめ":
    print("こんにちは,かめさん")

if name != "かめ":
    print(f"はじめまして,{name}さん")
文字列の比較 文字列を比べるときは,ダブルクォートを忘れないでください. if name == かめ: と書くと, 「かめ という変数」を探しに行って NameError になります. また,"かめ""カメ""亀" は すべて別の文字列です.前後に空白が入っていても別物になります.

5.2.4 === の違い

ここは毎年まちがえます 等しいかどうかを調べるのは,イコールを 2 つ並べた == です. イコール 1 つ= は,前の章習った 代入(箱に入れる命令)でした. まったく別のものです.
書き方意味使う場所
x = 7x という箱に 7 を入れるふつうの行
x == 7x が 7 と等しいか調べる(True か False になる)if の条件式
= と == の使い分け
x = 7          # 代入.x が 7 になる
if x == 7:     # 比較.x が 7 かどうか調べる
    print("7 です")

if x = 7:      # ← これは SyntaxError
    print("7 です")
Python は親切にできている Python では if x = 7: と書くと文法エラーになるので, その場ですぐ気づけます. === の打ち間違いは,どんなに慣れた人でもやります. Python は,この間違いをそもそも書けないようにしてあるのです.
虫食い虫食い 5-B 比較演算子を選ぶ

コメントに書いたとおりの結果になるよう, ____ に比較演算子を入れてください. 使う記号は == != < <= > >= のどれかです.

fill2_compare.py
x = 7

print(x ____ 7)      # True  と出したい(等しい)
print(x ____ 7)      # False と出したい(等しくない)
print(x ____ 10)     # True  と出したい(より小さい)
print(x ____ 7)      # True  と出したい(以上)
print(x ____ 6)      # False と出したい(以下)

5.3 そうでなければ — else

「成立したらこちら,しなかったらあちら」と2 つに分けたいときは, else を使います.

if - else の形
if 条件式:
    処理A          ← 成立したときだけ実行
else:
    処理B          ← 成立しなかったときだけ実行
  • else の行にもコロンが要ります.
  • else のうしろには条件を書きません(「それ以外のすべて」という意味だからです).
  • ifelse同じ深さに書きます.
  • 処理A と処理B のどちらか一方だけが必ず実行されます.両方は実行されません.
条件式処理A処理B成立不成立
図 5.5 if - else の流れ図.道が 2 つに分かれ,またひとつに戻る.

5.3.1 入力に応じて描くものを変える

「番号を入力すると,その絵を描く」プログラムです.

else_picture.py
from turtle import *

print("描きたい絵の番号を入力してください(1: 家 / それ以外: 星)")
number = int(input("番号 > "))

pensize(3)

if number == 1:
    # ---- 家を描く ----
    print("家を描きます")
    pencolor("saddlebrown")
    length = 110
    lt(60)
    fd(length)
    rt(120)
    fd(length)
    rt(120)
    fd(length)
    lt(90)
    fd(length)
    lt(90)
    fd(length)
    lt(90)
    fd(length)
    lt(90)
    fd(length)
else:
    # ---- 星を描く ----
    print("星を描きます")
    pencolor("goldenrod")
    length = 170
    rt(18)
    fd(length)
    rt(144)
    fd(length)
    rt(144)
    fd(length)
    rt(144)
    fd(length)
    rt(144)
    fd(length)
    rt(144)

ht()
done()

コンソールの入力行の 12 に書き換えて,実行し直してください. 描かれる絵が変わります.

図 5.6 1 を入力したとき
図 5.7 2 を入力したとき
ヒント if の中身も else の中身も, 何行でも書けます.字下げさえそろっていれば, その中でさらに pu()pencolor() を使ってもかまいません. 長くなってきたら,コメントで # ---- 家を描く ---- のように見出しを付けると読みやすくなります.
虫食い虫食い 5-C 正方形か正三角形か

1 と入力されたら正方形を,それ以外なら正三角形を描きます. ____ を 2 か所埋めてください. 1 つめは比較の記号,2 つめは「そうでなければ」の 1 行です.

fill4_else.py
from turtle import *

n = int(input("1 なら正方形,それ以外なら正三角形 > "))

pensize(3)

if n ____ 1:
    pencolor("navy")
    fd(120)
    lt(90)
    fd(120)
    lt(90)
    fd(120)
    lt(90)
    fd(120)
    lt(90)
____
    pencolor("crimson")
    fd(120)
    lt(120)
    fd(120)
    lt(120)
    fd(120)
    lt(120)

ht()
done()

5.4 いくつにも分ける — elif

3 つ以上に分けたいときは elif を使います. elifelse if を縮めた言葉です.

if - elif - else の形
if 条件式1:
    処理A
elif 条件式2:
    処理B
elif 条件式3:
    処理C
else:
    処理D
  • elifいくつでも並べられます.
  • 最後の else省略できます(どれにも当てはまらなければ,何もしない).
  • 上から順に条件を調べ,最初に成立したものだけを実行します.
  • 1 つ実行したら,残りの elif調べもしません
条件式1条件式2処理C処理A処理B不成立不成立成立成立
図 5.8 elif の流れ図.上から順に調べ,どれか 1 つだけを通る.

5.4.1 評点をグレードに変える

成績は,評点に応じて 「秀」「優」「良」「可」「不可」の 5 段階に分けられます. これをプログラムにしてみましょう.

grade.py
print("評点をグレードに変換します")
score = int(input("評点(0〜100)を入力してください > "))

if score >= 90:
    grade = "秀"
elif score >= 80:
    grade = "優"
elif score >= 70:
    grade = "良"
elif score >= 60:
    grade = "可"
else:
    grade = "不可"

print(f"評点 {score} 点は「{grade}」です")

コンソールの入力行の数を 957240 などに 変えて,すべての枝を通してみてください.

5.4.2 書く順番で結果が変わる

順番を間違えると全員「可」になる elif上から順に調べます.だから, 細かい条件(きびしい条件)から先に書く必要があります.
順番を間違えた例
# ← まちがった順番
if score >= 60:
    grade = "可"        # 95 点でも,ここで決まってしまう!
elif score >= 70:
    grade = "良"        # ここには永久にたどりつかない
elif score >= 90:
    grade = "秀"

95 点のときを考えてみてください. まず score >= 60 を調べます.95 は 60 以上なので成立します. ここで grade = "可" が実行され,残りの elif調べられることなく飛ばされます

エラーにならないバグ このプログラムはエラーになりません. ただ結果が間違っているだけです.こういう間違いが,いちばん見つけにくいバグです. elif を書いたら,それぞれの枝を必ず 1 回は通して 確かめる習慣をつけてください.

5.4.3 elif と「if を並べる」は違う

elif を使わず,if をいくつも並べて書くこともできます. しかし意味が変わります

書き方動き
if - elif - elifどれか 1 つだけが実行される.1 つ決まったら残りは調べない
if - if - ifそれぞれ独立に調べられる.当てはまればいくつでも実行される
multi_if.py
score = 95

print("--- elif で書いた場合 ---")
if score >= 60:
    print("可以上")
elif score >= 70:
    print("良以上")
elif score >= 90:
    print("秀")

print("--- if を並べた場合 ---")
if score >= 60:
    print("可以上")
if score >= 70:
    print("良以上")
if score >= 90:
    print("秀")

前半は 可以上 の 1 行だけ, 後半は 可以上良以上 の 3 行が出ます. 「どれか 1 つを選びたい」のか「当てはまるものを全部やりたい」のかで 使い分けてください.

虫食い虫食い 5-D グレード判定の境目

評点をグレードに変える elif の, 境目の数が抜けています. ____ を埋めて完成させてください. 秀は 90 点以上,優は 80 点以上,良は 70 点以上,可は 60 点以上です.

fill4_grade.py
score = int(input("評点(0〜100)を入力してください > "))

if score >= ____:
    grade = "秀"
elif score >= ____:
    grade = "優"
elif score >= ____:
    grade = "良"
elif score >= ____:
    grade = "可"
else:
    grade = "不可"

print(f"評点 {score} 点は「{grade}」です")

5.5 条件を組み合わせる — andornot

「80 点以上かつ 90 点未満」のように, 2 つ以上の条件をまとめて判定したいことがあります. このときに使うのが論理演算子です.

演算子書き方成立するのは
andA and BA B が両方とも成立するとき
orA or BA B のどちらか一方でも成立するとき
notnot AA が成立しないとき(成立・不成立をひっくり返す)
記号ではなく英単語で書く Python の論理演算子は英単語です. そのぶん,声に出して読めばそのまま意味になります. 「score >= 80 and score < 90」は 「スコアが 80 以上 かつ スコアが 90 未満」です.

5.5.1 成立するかしないかの表

ABA and BA or Bnot A
TrueTrueTrueTrueFalse
TrueFalseFalseTrueFalse
FalseTrueFalseTrueTrue
FalseFalseFalseFalseTrue
logic.py
score = 85

print(score >= 80 and score < 90)     # True  (両方とも成立)
print(score >= 80 and score < 85)     # False (2 つめが不成立)
print(score < 60 or score >= 90)      # False (どちらも不成立)
print(score == 85 or score == 100)    # True  (1 つめが成立)
print(not (score >= 90))              # True  (90 以上ではない)

5.5.2 範囲で判定する

elif を使わずに,and だけで同じ判定を書くこともできます. 2 通りの書き方を並べて見てください.

range.py
score = int(input("評点(0〜100)を入力してください > "))

if score >= 90:
    print("秀")
if score >= 80 and score < 90:
    print("優")
if score >= 70 and score < 80:
    print("良")
if score >= 60 and score < 70:
    print("可")
if score < 60:
    print("不可")

こちらは if を並べているだけなので, それぞれの条件が重ならないように自分で気を配る必要があります. その代わり,どの行も単独で読めるという良さがあります. elif のほうが短く書けますが,どちらが読みやすいかは場合によります.

Python ならではの書き方 Python では,数学と同じように 80 <= score < 90つなげて書くことができます. score >= 80 and score < 90 とまったく同じ意味です.
Python だけの便利な書き方
if 80 <= score < 90:
    print("優")
数学で書くときと同じ形のまま書けます.

5.5.3 入力が正しいか確かめる

or は,「おかしな入力をはじく」のによく使います.

guard.py
from turtle import *

length = int(input("1 辺の長さ(10 以上 200 以下)を入力してください > "))

if length < 10 or length > 200:
    print(f"{length} では描けません.10 以上 200 以下にしてください.")
else:
    print(f"1 辺 {length} の正方形を描きます")
    pensize(3)
    pencolor("royalblue")
    fd(length)
    lt(90)
    fd(length)
    lt(90)
    fd(length)
    lt(90)
    fd(length)
    lt(90)

ht()
done()

コンソールの入力行に 500 にして実行すると, 絵は描かれずに注意のメッセージだけが出ます. このように,処理する前に入力を確かめることを 入力チェックといいます.

ヒント この条件は not (10 <= length <= 200) とも書けます. 「10 以上 200 以下ではない」と読みます. どちらでも同じですが,読んで意味が分かるほうを選んでください.
虫食い虫食い 5-E 条件を組み合わせる

____andornot のどれかを入れて,コメントのとおりに動くようにしてください.

fill5_logic.py
age = int(input("年齢を入力してください > "))

# 18 歳以上 かつ 65 歳未満 のとき
if age >= 18 ____ age < 65:
    print("はたらきざかりです")

# 0 歳未満 または 120 歳より上 のとき(ありえない値)
if age < 0 ____ age > 120:
    print("その年齢はありえません")

# 20 歳以上 ではない とき
if ____ (age >= 20):
    print("お酒は飲めません")

5.5.4 組み合わせるときの順番とかっこ

andor同じ行に混ぜて書くと, どちらが先に計算されるかが問題になります. 第 3 章で,かけ算は足し算より先に計算されると習いました. 論理演算子にも,それとまったく同じように順番が決まっています.

順番演算子読み方
1(先)( ) の中かっこの中はいつでも最優先
2not〜でない
3andかつ
4(後)orまたは

つまり A or B and C は,A or (B and C) と 読まれます.(A or B) and C のつもりで書くと,結果が変わってしまいます.

priority.py
a = True
b = True
c = False

print(a or b and c)        # True    b and c が先 → True or False
print((a or b) and c)      # False   かっこの中が先 → True and False

print(not b and c)         # False   not b が先 → False and False
print(not (b and c))       # True    かっこの中が先 → not False
かっこは多めに 4 行とも,読み方が 1 つ変わるだけで答えがひっくり返っています. 迷ったら,かっこを付けてください. 余分なかっこがあってもエラーにはなりませんし,遅くもなりません. 読む人に書いた人の意図が伝わるという,大きな利点があります.

条件が 3 つ以上になるときは, かっこで「ひとかたまり」を作ってから組み合わせると読みやすくなります. 次は「2 つとも偶数」または「2 つとも 3 の倍数」のときだけ成立する条件です.

complex_cond.py
x = int(input("x を入力してください > "))
y = int(input("y を入力してください > "))

# (x も y も偶数)または(x も y も 3 の倍数)
if (x % 2 == 0 and y % 2 == 0) or (x % 3 == 0 and y % 3 == 0):
    print("条件に当てはまります")
else:
    print("当てはまりません")

%(余り)は第 3 章で習いました. x % 2 == 0 は「x は偶数」,x % 3 == 0 は「x は 3 の倍数」です. コンソールの入力行を 486957 に変えて,3 通りとも試してみてください.

もうひとつ覚えておくと得をするのが,not内側に配る 書き換えです.not をかっこの中へ入れると, andor入れかわります

この条件これと同じ意味
not (A and B)(not A) or (not B)
not (A or B)(not A) and (not B)

5.5.3 の入力チェックが,まさにこの関係でした. 「10 以上 200 以下ではない」(not (10 <= length <= 200))と, 「10 より小さいまたは 200 より大きい」 (length < 10 or length > 200)は,まったく同じ条件です. どちらで書いてもかまいませんが,読んで意味が分かるほうを選んでください.

orand の取りちがえ よくある間違いが,「〜でない」を and でつなぐことです. 「1 でも 2 でもない」を kind != 1 and kind != 2 と書くのは正しく, kind != 1 or kind != 2 と書くといつでも成立してしまいます (kind が 1 なら 2 つめが成立,2 なら 1 つめが成立するからです). 上の表の 2 行目を使うと,not (kind == 1 or kind == 2)kind != 1 and kind != 2 と確かめられます.
虫食い虫食い 5-F 乗り物に乗れるかどうか

遊園地の絶叫マシンに乗れるかどうかを判定します. 乗れるのは,「12 歳以下ではない」かつ「120cm 以下ではない」ときです. ____andornot のどれかを入れて,完成させてください.

fill6_ride.py
age = int(input("年齢を入力してください > "))
height = int(input("身長(cm)を入力してください > "))

# 「12 歳以下ではない」かつ「120cm 以下ではない」
if ____ (age <= 12) ____ ____ (height <= 120):
    print("乗ることができます")
else:
    print("乗ることができません")

5.6 条件の中に,また条件

if の中に,さらに if を書くことができます. これを入れ子(ネスト)といいます. 内側の if は,さらに 4 つ字下げします.

nest.py
n = int(input("整数を入力してください > "))

if n >= 1:
    print("1 以上です")
    if n <= 3:
        print("しかも 3 以下です")
    else:
        print("でも 4 以上です")
else:
    print("0 以下です")

print("おしまい")

字下げの深さが,そのまま入れ子の深さを表しています. どの else がどの if の相手なのかは, 字下げの位置がそろっているかどうかで決まります.

この例は,and を使って次のように書き換えられます.

入れ子を and で書き換える
if n >= 1 and n <= 3:
    print("1 以上 3 以下です")
深くしすぎない 入れ子は 2 段までにしておくと読みやすいです. 3 段,4 段と深くなってきたら, and でまとめられないかelif で横に並べられないかを考えてみてください. 深い入れ子は,書いた本人にも読めなくなります.

5.6.1 入れ子で絵を選ぶ

nest_draw.py
from turtle import *

kind = int(input("1: 四角 2: 三角 > "))
big = int(input("1: 大きく 2: 小さく > "))

if big == 1:
    length = 160
else:
    length = 70

pensize(3)

if kind == 1:
    pencolor("navy")
    fd(length)
    lt(90)
    fd(length)
    lt(90)
    fd(length)
    lt(90)
    fd(length)
    lt(90)
else:
    pencolor("crimson")
    fd(length)
    lt(120)
    fd(length)
    lt(120)
    fd(length)
    lt(120)

print(f"1 辺 {length} の図形を描きました")

ht()
done()

2 回の入力を変えると,4 とおりの絵が描けます. 条件を分けて書くことで,組み合わせが自然に作れました. もしこれを 1 つの if で書こうとすると, 4 つの枝それぞれに図形を描く命令を書くことになり,ずっと長くなります.

図 5.9 11
図 5.10 22

5.7 変数はどこから見えるか

変数には有効範囲(スコープ)という考え方があります. 「その名前がどこから使えるか」という範囲のことです. ここは思い違いの起きやすいところなので,落ち着いて読んでください.

5.7.1 if はスコープを作らない

Python では,ifelse の字下げは スコープを作りませんif の中で作った変数は,if を抜けたあともそのまま使えます

scope1.py
n = 5

if n > 3:
    message = "大きい"        # if の中で作った

print(message)                # if の外でも使える!
変数処理A(if の中)処理B(else の中)if を抜けたあと
z(if より前で作った)使える使える使える
x(if の中で作った)使えるまだ無い条件が成立していれば使える
y(else の中で作った)まだ無い使える条件が不成立だったら使える

「使えない」のではなく「まだ作られていない」という言い方になります. そこが大事なところです.

5.7.2 だから起きる事故

ときどきだけ落ちるプログラム 条件が成立しなかったとき,その変数は作られません. その状態で使おうとすると NameError になります. しかもある入力のときだけエラーになるので,たちが悪いです.
scope2.py
n = 1                         # ← 3 以下なので if は成立しない

if n > 3:
    message = "大きい"        # 実行されない = message は作られない

print(message)                # NameError: name 'message' is not defined

直し方は簡単です.if より前に,初期値を入れておくのです.

scope3.py
n = 1

message = "小さい"            # ← 先に初期値を入れておく

if n > 3:
    message = "大きい"        # 成立したときだけ上書きする

print(message)                # どちらの場合も動く
else を書けば安全 if / elif / elseすべての枝で変数に値を入れているなら,初期値は要りません. 5.4 節のグレード判定がそうでした(どの枝でも grade に値を入れています). else を書かないときほど危ないと覚えておいてください.
では Python のスコープの区切りは何か Python にもスコープはあります.ただし,区切りになるのは iffor ではなく関数です. def で作った関数の中で作った変数は,その関数の中だけで生きています. 関数は第 13 章で習いますので,そのときにあらためて説明します. 今のところは「if はスコープを作らない」とだけ覚えてください.

5.8 乱数と組み合わせる

5.8.1 おみくじ

前の章の乱数と,今回の条件分岐を組み合わせると,おみくじが作れます. 1 から 10 までの数をでたらめに選び,その数に応じて結果を変えます.

omikuji.py
import random
from turtle import *

number = random.randint(1, 10)     # 1 から 10 までのどれか
print(f"(引いた番号は {number} でした)")

if number == 1:
    result = "凶"
elif number <= 4:
    result = "小吉"
elif number <= 8:
    result = "中吉"
else:
    result = "大吉"

print(f"今日の運勢は「{result}」です")

# 画面にも大きく出す
ht()
pencolor("crimson")
pu()
goto(0, 60)
pd()
write(result, align="center", font=("Arial", 64, "bold"))

# 大吉のときだけ,お祝いの星を描く
if result == "大吉":
    pencolor("gold")
    pensize(4)
    pu()
    goto(-100, -60)
    pd()
    fd(200)
    rt(144)
    fd(200)
    rt(144)
    fd(200)
    rt(144)
    fd(200)
    rt(144)
    fd(200)
    rt(144)

done()
大吉
図 5.11 「大吉」が出たとき
中吉
図 5.12 「中吉」が出たとき(星は描かれない)

何度か実行してみてください.まれに「大吉」が出て,星が描かれます. 確率は 10 分の 2です(9 と 10 のとき).

elif の条件が短くて済む理由 number <= 4 という条件が「2・3・4」を意味するのは, その手前で number == 1 がすでに調べ終わっているからです. elif「ここまでのどれにも当てはまらなかったうえで」 という意味を持っています. number >= 2 and number <= 4 と書かなくてよいのは,このためです.

5.8.2 じゃんけん — データのモデル化

コラム:グー・チョキ・パーをどう表すか じゃんけんをプログラムにしたいとき,最初にぶつかる問題があります. 「グー」「チョキ」「パー」を,コンピュータにどう覚えさせるかです. コンピュータは「グー」という概念を知りません.
  • グーを 1,チョキを 2,パーを 3 と決める
  • random.randint(1, 3) で手を選ぶ
  • if でその数を見て,対応する絵を描く
このように,現実のものごとをコンピュータが扱える形に置き換える作業を モデル化(データ構造の設計)といいます. プログラムを作るとき,コードを書く前に必ず通る作業です. 今回は「3 種類のものを 1・2・3 という数で表す」という,いちばん簡単なモデル化をしました.
janken.py
import random
from turtle import *

# グーを 1,チョキを 2,パーを 3 とする
hand = random.randint(1, 3)

pensize(8)
pencolor("darkslateblue")

if hand == 1:
    print("グー")
    dot(160)
elif hand == 2:
    print("チョキ")
    lt(60)
    fd(150)
    bk(150)
    rt(120)
    fd(150)
else:
    print("パー")
    lt(30)
    fd(150)
    bk(150)
    lt(30)
    fd(150)
    bk(150)
    lt(30)
    fd(150)
    bk(150)
    lt(30)
    fd(150)
    bk(150)
    lt(30)
    fd(150)
    bk(150)

ht()
done()
図 5.13 hand = 1 グー
図 5.14 hand = 2 チョキ
図 5.15 hand = 3 パー
ヒント 絵は思い切り簡単にしてあります. グーは点,チョキは 2 本の線,パーは 5 本の線です. もっとそれらしい絵にするのは,演習の課題にします.

5.9 この章で出てきた書き方

書き方意味
if 条件式:条件が成立したときだけ,字下げした部分を実行する
elif 条件式:ここまでが不成立で,この条件が成立したとき.いくつでも書ける
else:ここまでのどれも不成立だったとき.条件は書かない
字下げ(半角 4 つ)どこまでが if の中身かを表す
==等しい(イコール 2 つ).= は代入なので別物
!=等しくない
> <より大きい/より小さい
>= <=以上/以下(等しいときも成立)
andかつ(両方とも成立)
orまたは(どちらか一方でも成立)
not〜でない(成立・不成立をひっくり返す)
( )条件のかたまりを作る.notandor の順に計算されるので,迷ったら付ける
True False成立/不成立.bool 型.先頭だけ大文字
a <= x < b範囲のつなげ書き(Python だけの書き方)
pass何もしないと書く.ブロックを空にできないときに置く
random.randint(a, b)a 以上 b 以下の整数を 1 つ(前の章の復習)

演習

「▶ この演習を開く」で右側に読み込み,出発点のプログラムを 自分で発展させて作品にしてください. input() を使う演習にはコンソールの入力行に値が入っています. すべての枝を 1 回ずつ通して確かめてから仕上げてください.

全部の枝を通すこと 条件分岐のあるプログラムは,1 回実行しただけでは確かめたことになりませんelif が 5 本あるなら,入力を 5 通り変えて 5 回実行してください. これをテストといい,プロのプログラマも同じことをしています.
演習演習 5-1 図形屋さん

番号を入力すると,その図形を描く「図形屋さん」を作ります. 出発点は 1・2・それ以外の 3 とおりしかありません. elif を増やして,5 種類以上描けるようにしてください.

  1. 1: 正五角形 2: 正六角形 3: 正八角形 4: 星 5: こんぺいとう それ以外: トライフォース のように品ぞろえを増やす.
  2. 図形の大きさも入力で決められるようにする(input() をもう 1 回使う).
  3. おかしな大きさ(0 以下,500 以上など)が入力されたら,or を使ってはじき,メッセージを出す.
  4. 余裕があれば:色も番号で選べるようにする,図形を 2 つ描いて重ねる,など自由に発展させる.
1 を入力したときの例
演習演習 5-2 おみくじ

乱数と条件分岐を使ったおみくじを作ります. 出発点は「大吉・中吉・小吉・凶」の 4 段階です.

  1. 段階を増やす(「末吉」「大凶」など).それぞれの出る確率も自分で決める.
  2. 結果に応じて描く絵を変える(大吉は星,凶は雨など).
  3. 結果に応じて色や文字の大きさを変える
  4. 余裕があれば:名前を入力してもらい,f 文字列で「○○さんの運勢は…」と表示する.
確率の決め方 random.randint(1, 100) にすると, 確率を 1 % きざみで決められます. 「1〜5 なら大凶(5 %)」「6〜30 なら凶(25 %)」という具合です.
演習演習 5-3 評点グレード変換

評点を入力すると,成績のグレード (A・B・C・D・F)を表示するプログラムです.

  1. 0 未満や 100 より大きい評点が入力されたら,or を使ってはじき,注意を表示する.
  2. グレードだけでなく GP(秀 4・優 3・良 2・可 1・不可 0)も表示する.
  3. グレードに応じてメッセージを変える(「よくできました」など).
  4. 余裕があれば:グレードに応じて,タートルに違う絵を描かせる(秀なら星 5 つ,可なら星 1 つ,など).
演習演習 5-4 じゃんけん

コンピュータがじゃんけんの手を出すプログラムです. 出発点の絵はごく簡単なものなので, もっとそれらしい手を描いてください.

  1. グー・チョキ・パーの絵を,指や輪郭が分かるように描き直す.
  2. 自分の手も入力してもらい,ifand勝敗を判定する(グーはチョキに勝つ,など).
  3. あいこのときは「あいこです」と表示する.
  4. 余裕があれば:勝った回数を数えて表示する,手の強さを変える(パーが出にくい,など).
勝敗の判定 勝敗の判定は,全部で 9 とおりしかありません. ifelif を並べて書けば必ず書けます. 短く書く方法もありますが(あいこ・勝ち・負けを引き算の余りで求める), まずは素直に 9 とおり並べてみてください.
演習演習 5-5 体型評価プログラム

身長と体重を入力すると,BMI 指数を計算し, その値から体型を判定するプログラムです.

  • BMI = 体重(kg) ÷ 身長(m) ÷ 身長(m).身長の単位に注意してください(cm で入力させるなら 100 で割る).
  • 判定は,18.5 未満=やせ,18.5 以上 25 未満=標準,25 以上 35 未満=肥満,35 以上=高度肥満.
  • BMI は小数第 2 位で四捨五入して表示する(前の章習った int(x * 10 + 0.5) / 10 を使う).
  • 始めと終わりに「開始しました」「終了しました」と表示する.
  • 余裕があれば:判定に応じてメッセージや絵を変える,年齢も聞いて判定基準を変える,など.
0 で割らないように 身長を 0 と入力されると,0 で割ることになり ZeroDivisionError で止まります. if を使って,計算する前にはじいてください.
自由演習 5-6 自由制作:判断するプログラム

条件分岐を使って,自由に作品を作ってください. 状況を見て動きが変わることが,今回の作品の条件です.

  • if3 か所以上使うこと(elif も 1 つと数えてよい)
  • else1 回以上使うこと
  • andornot のどれかを1 回以上使うこと
  • input()random.randint() で,実行するたびに結果が変わるようにすること
  • 先頭のコメントに題名・氏名・日付を書くこと
  • すべての枝を 1 回ずつ通して確かめてから仕上げること
題材のヒント 題材に迷ったら:西暦を入力すると和暦(令和・平成・昭和)に変換するプログラム, 月を入力すると季節と,季節に応じた絵を描くプログラム, 性格診断(いくつか質問して点数を足し,点数で結果を分ける), 自動販売機(金額と商品番号を入力して,買えるかどうか判定する), 信号機(乱数で赤・青・黄を選んで描く),などはいかがでしょうか.

まとめ

  • if 条件式: と書き,次の行から4 つ字下げする.コロンと字下げがセットでブロックを作る.
  • 条件式は == != < <= > >= で書き,結果は TrueFalsebool 型)になる.
  • == は比べる,= は入れる.まったく別物.
  • else で 2 つに,elif でいくつにも分けられる.elif上から順に調べ,最初に成立した 1 つだけを実行する.だからきびしい条件から先に書く
  • and(かつ)・or(または)・not(〜でない)で条件を組み合わせる.
  • 計算の順番は notandorかたまりはかっこで囲むnot (A and B)(not A) or (not B) と同じ意味になる.
  • Python では ifスコープを作らないif の中で作った変数も外から見えるが,条件が不成立なら作られないので NameError に注意.先に初期値を入れておくか,すべての枝で値を入れる
  • 乱数と条件分岐を組み合わせると,おみくじやじゃんけんが作れる.現実のものごとを数で表すことをモデル化という.
  • 条件分岐のあるプログラムは,すべての枝を通して確かめる.

次の回では,繰り返しを習います. for を使うと,fdrt を 10 回書いていた正十角形が, たった 3 行で書けるようになります. 第 2 章と第 3 章で「面倒だ」と感じたことが,いっぺんに解決します.