8. if 文による判断
これまでに書いてきたプログラムでは、Python は上から下へ、1 行ずつ順番にすべてのコードを実行してきました。しかし、現実のプログラムには「判断」が必要です。状況に応じて実行するコードを変えなければなりません。エラーメッセージを表示すべきでしょうか?割引を計算すべきでしょうか?もう一度入力を求めるべきでしょうか?その答えは状況次第です。
条件文 (conditional statement) を使うと、プログラムにこのような判断をさせることができます。特定の条件が真 (True) のときだけ、特定のコードブロックを実行し、それ以外のときはスキップさせることができます。本章では、Python の if 文とそのバリエーションを紹介します。これらはプログラムで意思決定を行うための土台となるものです。
条件文を使いこなせるようになると、ユーザー入力に賢く反応し、さまざまな状況を適切に処理し、論理的な推論を必要とする問題を解決できるプログラムを書けるようになります。
8.1) シンプルな if 文
Python におけるもっとも基本的な判断の形が、シンプルな if 文です。これは Python に「この条件が真なら、このコードブロックを実行しなさい。そうでなければスキップして先へ進みなさい」と伝えます。
8.1.1) if 文の構造
if 文の基本構文は次のとおりです。
if condition:
# condition が True のときに実行するコード
statement1
statement2
# ... さらに文が続く各部分を分解して見てみましょう。
ifキーワード: 条件文の開始を表します- 条件 (condition):
TrueまたはFalseになるブール式 (第 7 章で扱いました) - コロン (
:): 必須であり、条件行の終わりを示します - インデントされたコードブロック:
ifの下にインデントされたすべての文は、その条件がTrueのときにだけ実行されます
インデントは Python では非常に重要です。 インデントされた行は if 文に属する コードブロック (code block) を構成します。Python はインデント (一般的にはスペース 4 つ) を使って、どの文が条件ブロックの一部なのかを判断します。
次に簡単な例を示します。
# temperature_check.py
temperature = 30
if temperature > 25:
print("It's a warm day!")
print("Consider wearing light clothing.")
print("Have a great day!") # これは常に実行されます出力:
It's a warm day!
Consider wearing light clothing.
Have a great day!この例では:
- 条件
temperature > 25はTrueになります (30 > 25 なので) - インデントされた 2 行の
print()はifブロックの一部なので、どちらも実行されます - 最後の
print()文はインデントされていないので、ifブロックの外にあり、常に実行されます
次に、条件が False のときに何が起きるかを見てみましょう。
# temperature_check_cool.py
temperature = 18
if temperature > 25:
print("It's a warm day!")
print("Consider wearing light clothing.")
print("Have a great day!") # これは常に実行されます出力:
Have a great day!今回は:
- 条件
temperature > 25はFalseになります (18 は 25 より大きくないため) - インデントされた 2 行は完全にスキップされます
- 最後の
print()はifブロックの外にあるため、今回も実行されます
8.1.2) 第 7 章の条件式を使う
第 7 章で扱った任意のブール式 (boolean expression) を、if 文の条件として使うことができます。これには次のものが含まれます。
比較演算子 (comparison operators):
# voting_eligibility.py
age = 16
if age >= 18:
print("You are eligible to vote.")
# 何も表示されません。16 >= 18 は False だからです
score = 85
if score >= 60:
print("You passed the exam!") # Output: You passed the exam!in と not in によるメンバーシップテスト (membership tests):
# user_access.py
username = "alice"
banned_users = ["bob", "charlie", "dave"]
if username not in banned_users:
print(f"Welcome, {username}!") # Output: Welcome, alice!
favorite_color = "blue"
if "u" in favorite_color:
print("Your favorite color contains the letter 'u'.") # Output: Your favorite color contains the letter 'u'.ブール値そのものを条件にする:
# weather_check.py
is_raining = True
if is_raining:
print("Don't forget your umbrella!") # Output: Don't forget your umbrella!真偽値判定 (truthiness と falsiness) (第 7.4 節より):
# name_input.py
user_input = input("Enter your name: ")
if user_input: # 空文字列は偽 (falsy)、空でない文字列は真 (truthy)
print(f"Hello, {user_input}!")
else:
print("You didn't enter a name.")8.1.3) if ブロック内の複数の文
if ブロック内には、必要なだけ多くの文を含めることができます。if 行の下でインデントされたすべての文が、そのブロックに属します。
# bank_withdrawal.py
balance = 1500
withdrawal = 200
if withdrawal <= balance:
balance = balance - withdrawal # balance から withdrawal を差し引く
print(f"Withdrawal successful!")
print(f"Your new balance is: ${balance}")
print("Thank you for your transaction.")
print("Transaction complete.") # 常に実行されます出力:
Withdrawal successful!
Your new balance is: $1300
Thank you for your transaction.
Transaction complete.withdrawal <= balance が True なので、4 行すべてが実行されます。では、引き出し額を 2000 に変えてみましょう。
# bank_withdrawal_insufficient.py
balance = 1500
withdrawal = 2000
if withdrawal <= balance:
balance = balance - withdrawal
print(f"Withdrawal successful!")
print(f"Your new balance is: ${balance}")
print("Thank you for your transaction.")
print("Transaction complete.") # 常に実行されます出力:
Transaction complete.今回は条件が False なので、インデントされた文は 1 行も実行されません。残高は 1500 のまま変わりません。
8.2) if-else による二者択一
多くの場合、「条件が真のときはこのコードを実行し、偽のときは別のコードを実行する」といった二者択一が必要になります。if-else 文は、このような「どちらか一方」を選ぶ判断を扱います。
8.2.1) if-else の構造
構文は次のとおりです。
if condition:
# condition が True のときに実行するコード
statement1
statement2
else:
# condition が False のときに実行するコード
statement3
statement4else 節は代わりの経路を提供します。2 つのブロックのうち、実行されるのは必ずどちらか一方だけであり、両方が実行されたり、どちらも実行されないということはありません。
実用的な例を見てみましょう。
# age_verification.py
age = int(input("Enter your age: "))
if age >= 18:
print("You are an adult.")
print("You can vote in elections.")
else:
print("You are a minor.")
print("You cannot vote yet.")
print("Thank you for providing your age.")25 と入力した場合:
You are an adult.
You can vote in elections.
Thank you for providing your age.15 と入力した場合:
You are a minor.
You cannot vote yet.
Thank you for providing your age.条件に応じて、2 つのブロックのうち必ずどちらか一方だけが実行されることに注目してください。最後の print() 文は、どちらのブロックにも属さないため、毎回実行されます。
8.2.2) 二値の判断を行う
if-else は、結果がちょうど 2 通りしかない二値の判断に最適です。
# even_odd_checker.py
number = int(input("Enter a number: "))
if number % 2 == 0:
print(f"{number} is even.")
else:
print(f"{number} is odd.")# password_verification.py
stored_password = "python123"
entered_password = input("Enter password: ")
if entered_password == stored_password:
print("Access granted.")
print("Welcome to the system!")
else:
print("Access denied.")
print("Incorrect password.")8.3) if-elif-else による複数の選択肢
現実の判断では、選択肢が 2 つでは足りないことがよくあります。通常配送、速達、翌日配送のどれで発送すべきか?成績は A, B, C, D, F のどれか?このような、互いに排他的な複数の選択肢は、if-elif-else 連鎖 (chain) で扱います。
8.3.1) if-elif-else の構造
構文は次のとおりです。
if condition1:
# condition1 が True のときに実行
block1
elif condition2:
# condition1 が False で condition2 が True のときに実行
block2
elif condition3:
# condition1 と condition2 が False で、condition3 が True のときに実行
block3
else:
# すべての条件が False のときに実行
block4if-elif-else 連鎖についての重要なポイント:
elifは "else if" の略: 追加の条件をチェックするためのものです- 順番が重要: Python は上から順に条件を評価します
- 最初に真になった条件が勝ち: どれかの条件が
Trueになったら、そのブロックを実行し、残りはスキップされます - 実行されるブロックは高々 1 つ: 連鎖の中で、実行されるブロックは最大 1 つです
elseは任意: それまでの条件で扱われなかったすべてのケースを受け止めます
実用的な例を見てみましょう。
# grade_calculator.py
score = int(input("Enter your exam score (0-100): "))
if score >= 90:
grade = "A"
print("Excellent work!")
elif score >= 80:
grade = "B"
print("Good job!")
elif score >= 70:
grade = "C"
print("Satisfactory.")
elif score >= 60:
grade = "D"
print("You passed, but consider reviewing the material.")
else:
grade = "F"
print("Unfortunately, you did not pass.")
print(f"Your grade is: {grade}")85 と入力した場合:
Good job!
Your grade is: Bこのときに何が起きているかを追ってみましょう。
score >= 90をチェック: False (85 は 90 以上ではない) なので、このブロックはスキップscore >= 80をチェック: True (85 >= 80) なので、このブロックを実行- すでに一致する条件が見つかったので、それ以降の
elifとelseブロックはすべてスキップ
55 と入力した場合:
Unfortunately, you did not pass.
Your grade is: Fすべての条件が False になるため、else ブロックが実行されます。
8.3.2) elif 連鎖で順番が重要な理由
elif 連鎖では、条件の順番がとても重要です。Python は、最初に True になった条件で処理を止めるからです。次のような誤った成績判定を考えてみましょう。
# INCORRECT ORDER - Don't do this!
score = 85
if score >= 60: # ここが最初に一致してしまいます!
grade = "D"
elif score >= 70:
grade = "C"
elif score >= 80:
grade = "B"
elif score >= 90:
grade = "A"
else:
grade = "F"
print(f"Your grade is: {grade}") # Output: Your grade is: Dこれは誤った結果を出しています。85 点は本来 B のはずですが、score >= 60 が最初に評価されて True になるため、D になってしまいます。Python はその後の score >= 80 までたどり着きません。
常に、より「限定的な」条件から「一般的な」条件の順に並べましょう。
# CORRECT ORDER
score = 85
if score >= 90: # もっとも限定的
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
elif score >= 60:
grade = "D"
else: # もっとも一般的
grade = "F"
print(f"Your grade is: {grade}") # Output: Your grade is: B8.3.3) else を省いた elif の使い方
else 節は必須ではありません。特定のケースだけを処理し、それ以外は何もしなくてよい場合もあります。
# weekend_checker.py
day = input("Enter a day of the week: ").lower()
if day == "saturday" or day == "sunday":
print("It's the weekend! Time to relax.")
elif day == "friday":
print("It's Friday! The weekend is almost here.")
elif day in ["monday", "tuesday", "wednesday", "thursday"]:
print("It's a weekday. Time to work or study.")
# else 節はなし - どれにも一致しなければ何も起こりません
print("Have a great day!")"holiday" と入力した場合:
Have a great day!どの条件にも一致せず、else 節も存在しないので、最後の print() だけが実行されます。
8.4) ネストした if 文
ときには、「ある判断の中でさらに別の判断をする」必要があります。ネストした if 文 (nested if statement) では、ある条件文の中に別の条件文を入れることで、最初の条件が満たされたときにだけ、追加の条件をチェックできるようになります。
8.4.1) ネストした条件分岐を理解する
ネストした if 文は、まだ意味をなさない条件をチェックしないようにするのに役立ちます。たとえば、ユーザーがアカウントを持っていないのにパスワードを尋ねるのは意味がありません。ネストを使うと、現実世界の意思決定プロセスに合わせてロジックを構造化できます。現実世界では、多くの場合「先にある質問に答えてからでないと、次の質問が意味を持たない」からです。
ネストした if 文とは、単に別の if ブロック (または if-elif-else 連鎖) の内側に書かれた if 文のことです。
if outer_condition:
# outer_condition が True のときに実行されるコード
if inner_condition:
# outer_condition と inner_condition が両方 True のときに実行されるコード
inner_block
else:
# outer_condition は True だが inner_condition が False のときに実行
inner_else_block
else:
# outer_condition が False のときに実行
outer_else_block内側の if 文は、外側の条件が True のときにだけ評価されます。これによって、階層的な判断が作られます。
簡単な例を示します。
# account_login.py
has_account = input("Do you have an account? (yes/no): ").lower() == "yes"
if has_account:
print("Welcome back!")
password = input("Enter your password: ")
if password == "secret123":
print("Login successful!")
print("Access granted to your dashboard.")
else:
print("Incorrect password.")
print("Access denied.")
else:
print("Please create an account first.")
print("Visit our registration page.")"yes" と答え、正しいパスワードを入力した場合:
Welcome back!
Login successful!
Access granted to your dashboard."yes" と答え、間違ったパスワードを入力した場合:
Welcome back!
Incorrect password.
Access denied."no" と答えた場合:
Please create an account first.
Visit our registration page.パスワードチェックは、ユーザーがアカウントを持っている場合にだけ行われることに注目してください。これがネストの大きな利点です。必要のないチェックを避けることができます。
8.4.2) ネストした if 文を使う場面
ネストした if 文が役立つのは次のような場面です。
- ある判断が別の判断に依存しているとき: 先にある条件が満たされた場合にのみ、次の条件をチェックしたいとき
- 決定木 (decision tree) を作るとき: 各階層が可能性を絞り込んでいくとき
- 前提条件の検証: 詳細な条件をチェックする前に、基本的な条件をチェックしたいとき
- 不要なチェックを避けるとき: 早い段階で条件が満たされないとわかったら、コストの高い処理をスキップしたいとき
例: ローンの申請資格
# loan_eligibility.py
age = int(input("Enter your age: "))
if age >= 18:
print("Age requirement met.")
income = float(input("Enter your annual income: $"))
if income >= 30000:
print("Income requirement met.")
credit_score = int(input("Enter your credit score: "))
if credit_score >= 650:
print("Congratulations! You are eligible for a loan.")
print("Please proceed to the application form.")
else:
print("Sorry, your credit score is too low.")
print("Minimum required: 650")
else:
print("Sorry, your income is too low.")
print("Minimum required: $30,000")
else:
print("Sorry, you must be 18 or older to apply.")ここでは、決定木のような構造が作られています。年齢が 18 未満であれば、その先の収入やクレジットスコアは一切尋ねません。
8.4.3) 過度なネストを避ける
ネストは強力ですが、階層が深くなりすぎると、コードが読みにくくなり理解しづらくなります。次のような深いネストの例を見てみましょう。
# ネストが深すぎて追いにくい例
if condition1:
if condition2:
if condition3:
if condition4:
if condition5:
print("All conditions met!")これは読みづらく、保守もしにくいコードです。ネストを減らすための戦略をいくつか紹介します。
戦略 1: 条件を適切にまとめる
and 演算子については第 9 章で詳しく説明しますが、ここでは複数の条件を同時にチェックできるものだとだけ理解しておいてください。
# より良い書き方: 'and' を使って条件をまとめる (第 9 章で詳しく学びます)
# 'and' は複数の条件がすべて True かどうかをチェックします
if condition1 and condition2 and condition3 and condition4 and condition5:
print("All conditions met!")戦略 2: 早期リターン (early return) を使う (関数については第 19 章で学びます):
# 関数の中では、途中で return して抜けることができます
def check_eligibility(age, income, credit_score):
if age < 18:
return "Too young"
if income < 30000:
return "Income too low"
if credit_score < 650:
return "Credit score too low"
return "Eligible"戦略 3: 適切な場面では elif でフラットにする
# 範囲チェックのためにネストした if を使う代わりに
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
# ... というように続けます8.5) if 文でよくある落とし穴 (インデント、コロン、ロジック)
if 文では、経験豊富なプログラマーでもミスをすることがあります。この節では、初心者が特によく遭遇するエラーと、その回避方法を説明します。
8.5.1) インデントのエラー
Python では、どの文がどのブロックに属するのかをインデントで判断します。インデントのミスは、もっとも一般的なエラーの 1 つです。
問題 1: インデントの欠如
# INCORRECT - IndentationError
age = 20
if age >= 18:
print("You are an adult.") # インデントされていない!このコードは次のようなエラーになります。
File "example.py", line 4
print("You are an adult.")
^
IndentationError: expected an indented block解決策: if 文の下にあるブロックは必ずインデントしましょう。
# CORRECT
age = 20
if age >= 18:
print("You are an adult.") # 正しくインデントされている問題 2: インデントの不一致
# INCORRECT - スペースとタブの混在、またはスペース数の不一致
if temperature > 30:
print("It's hot!")
print("Stay hydrated!") # スペースが多すぎる - インデントが不一致解決策: 一貫したインデントを使いましょう (Python の標準はスペース 4 つです)。
# CORRECT
if temperature > 30:
print("It's hot!")
print("Stay hydrated!") # 同じインデント幅問題 3: ネストのインデントが間違っている
# INCORRECT - インデントのレベルが間違っている
if has_account:
print("Welcome!")
if password == "correct":
print("Login successful!") # もっと深くインデントする必要があります解決策: ネストが 1 段深くなるごとに、さらにインデントを追加します。
# CORRECT
if has_account:
print("Welcome!")
if password == "correct":
print("Login successful!") # ネストされたブロックとして正しくインデントされている8.5.2) コロンの付け忘れ
if、elif、else 行の末尾に付けるコロン (:) は必須です。これを忘れるのは非常によくあるミスです。
# INCORRECT - SyntaxError: コロンの欠如
if age >= 18
print("Adult")このコードは次のようなエラーになります。
File "example.py", line 2
if age >= 18
^
SyntaxError: invalid syntax解決策: 必ずコロンを付けましょう。
# CORRECT
if age >= 18:
print("Adult")同じことは elif と else にも当てはまります。
# CORRECT - すべての行にコロンが付いている
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
else:
grade = "F"8.5.3) 誤った比較演算子の使用
問題 1: 代入演算子 (=) と比較演算子 (==) の取り違え
# INCORRECT - これは age に 18 を代入しており、比較していません!
age = 20
if age = 18: # SyntaxError
print("You are 18")解決策: 比較には == を使います。
# CORRECT
age = 20
if age == 18:
print("You are 18")8.5.4) ロジックエラーによる到達不能コード
問題: 決して True にならない条件
# INCORRECT - この elif は決して実行されない
score = 85
if score >= 60:
print("You passed!")
elif score >= 80: # ここは決して実行されません!
print("You got a B!")score が 85 の場合、最初の条件 score >= 60 が True になるため、elif はチェックされません。条件の順番が間違っています。
解決策: 条件は、より限定的なものからより一般的なものへ並べます。
# CORRECT
score = 85
if score >= 80:
print("You got a B!")
elif score >= 60:
print("You passed!")8.5.5) 空の if ブロック
Python では、空の if ブロックを持つことはできません。
# INCORRECT - SyntaxError
if temperature > 30:
# 後でここにコードを追加する予定
print("Done")このコードは次のようなエラーになります。
File "example.py", line 3
print("Done")
^
IndentationError: expected an indented block解決策: 次の節で説明する pass 文を、プレースホルダーとして使います。
# CORRECT - プレースホルダーとして pass を使用
if temperature > 30:
pass # TODO: 後でここにコードを追加する
print("Done")8.6) pass を使ったブロックのプレースホルダー
コードを書いていると、「ここには if 文が必要だ」ということはわかっているのに、その中にどんなコードを書くかまだ決めていない、という状況になることがあります。Python では空のコードブロックは許されないので、「何もしないけれど構文的には正しいブロック」を作る方法が必要です。そこで使うのが pass 文です。
8.6.1) pass とは何か
pass 文は 何もしない操作 (null operation) です。Python が pass を実行しても、何も起こりません。これは、実装がまだ用意できていないときでも、構文的に正しいコードを書けるようにするためのプレースホルダーです。
if condition:
pass # 今のところは何もしないpass は、「ここにコードが必要なことはわかっているが、後で書きます」と Python に伝えるためのものだと考えてください。プログラムの構造をざっくり書き出している開発の途中段階で特に便利です。
8.6.2) pass が必要な理由
Python では、すべてのコードブロックに少なくとも 1 つの文が必要です。空のブロックは構文エラーになります。
# INCORRECT - これはエラーになります
if age >= 18:
# TODO: 成人向けの処理をここに追加
print("Done")エラー:
File "example.py", line 3
print("Done")
^
IndentationError: expected an indented blockpass を使うと、コードを構文的に正しくできます。
# CORRECT - プレースホルダーとして pass を使用
if age >= 18:
pass # TODO: 成人向けの処理をここに追加
print("Done")8.6.3) pass のよくある用途
用途 1: 開発中のプレースホルダー
プログラムの構造だけ先に書いておき、実装はまだ書いていない部分に使います。
# user_system.py
user_type = input("Enter user type (admin/user/guest): ").lower()
if user_type == "admin":
pass # TODO: admin 機能を実装
elif user_type == "user":
pass # TODO: user 機能を実装
elif user_type == "guest":
print("Welcome, guest! Limited access granted.")
else:
print("Invalid user type.")これにより、未実装部分にプレースホルダーを残したまま、プログラムを実行して実装済みの部分をテストできます。
用途 2: ある分岐では本当に何もしない場合
場合によっては、ある条件では本当に何もしたくないが、他の条件は処理したいということがあります。
# positive_numbers.py
# 正の数だけを処理する
number = int(input("Enter a number: "))
if number > 0:
result = number * 2
print(f"Double of {number} is {result}")
elif number == 0:
pass # 0 は有効だが特に何もする必要がない
else:
print("Negative numbers are not allowed.")8.6.4) 他の場面での pass
ここまでは if 文の中での pass の使用に焦点を当てましたが、Python を学んでいく中で、他の場面でも pass に出会うことになります。
- 関数 (第 20 章): 関数本体のプレースホルダー
- クラス (第 31 章): クラス定義のプレースホルダー
- ループ (第 11–12 章): ループ本体のプレースホルダー
- 例外処理 (第 29 章): エラーを意図的に無視するとき
今のところは、pass が「中身のないコードブロックを作るための道具」だということを覚えておけば十分です。
まとめ
この章では、条件文を使ってプログラムに「判断」をさせる方法を学び、プログラムをより賢く柔軟にしました。ここで、重要な概念をまとめましょう。
シンプルな if 文 は、条件が真のときだけコードを実行します。
if temperature > 30:
print("It's hot outside!")if-else 文 は、2 つの選択肢のどちらか一方を選びます。
if age >= 18:
print("Adult")
else:
print("Minor")if-elif-else 連鎖 は、互いに排他的な複数の選択肢を扱います。
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
else:
grade = "F"ネストした if 文 は、「判断の中でさらに判断をする」ために使います。
if has_account:
if password_correct:
print("Welcome!")
else:
print("Wrong password")
else:
print("Create an account")避けるべきよくある落とし穴:
if、elif、elseの後ろのコロンの付け忘れ- インデントのミスや不一致
- 比較に
==ではなく=を使ってしまう elif連鎖で条件の順番を誤るpassなしで空のブロックを作ってしまう
pass 文 は、開発中に空のブロックのプレースホルダーとして使える道具です。
これで、条件に基づいて賢く判断できるプログラムを書くための道具が揃いました。次の章では、複数の条件を組み合わせてより洗練された判断ロジックを作るための ブール論理演算子 (boolean logic operators) (and, or, not) を学びます。これによって、if 文はさらに強力で表現力豊かなものになります。