10. 条件式(if-else 式)の使い方
第8章では、if 文を使ってプログラム内で判断を行う方法を学びました。これらの文は、条件に基づいて異なるコードブロックを実行できるようにします。しかし、ときには 2 つのコードブロックではなく 2 つの値のどちらかを選びたい場合があります。Python はこのよくある状況のために、特別な構文を用意しています。それが 条件式 (conditional expressions) です。
条件式(他の言語では 三項式 (ternary expressions) や 三項演算子 (ternary operator) とも呼ばれます)を使うと、条件に基づいてどちらか一方の値を選ぶだけのときに、コンパクトな意思決定コードを書けます。特に、代入や、より大きな式を組み立てるときに便利です。
10.1) 条件式とは
条件式 (conditional expression) とは、条件に基づいて 2 つの値のうちどちらかに評価される単一の式です。どのコードブロックを実行するかを制御する if 文とは異なり、条件式はすぐに使える値を生成します。
よくあるシナリオを見てみましょう。たとえば、年齢で生徒を分類するプログラムを書いているとします。
# if 文を使う(すでに知っている方法)
age = 16
if age >= 18:
category = "adult"
else:
category = "minor"
print(f"Category: {category}") # Output: Category: minorこれは問題なく動きますが、実際には 2 つの文字列値のどちらかを選んでいるだけであることに注目してください。この程度の単純な判断にしては、構造がやや冗長です。以下は同じロジックを条件式で書いたものです。
# 条件式を使う
age = 16
category = "adult" if age >= 18 else "minor"
print(f"Category: {category}") # Output: Category: minorどちらのバージョンも結果は同一ですが、条件式のほうがよりコンパクトです。条件に基づいて category に 2 つの値のどちらかを直接代入します。
根本的な違いを理解する
重要な違いは、条件式は文ではなく 式 であるという点です。
- 式 (expression) は値に評価されるものです。代入、関数引数、他の式の内部など、値が期待される場所ならどこでも使えます。
- 文 (statement) は、アクションを実行する完全な命令ですが、値を生成しません。
# これは式です - 値を生成します
result = 10 if True else 20
# これは文です - アクションを実行しますが、それ自体が値ではありません
if True:
result = 10
else:
result = 20条件式は値を生成するため、特定の状況ではより柔軟に使えます。ただし、それが常に優れているという意味ではありません。この章の後半で、それぞれをいつ使うべきかを探っていきます。
10.2) if–else 式の構文
条件式の構文は次のパターンに従います。
value_if_true if condition else value_if_false各要素を分解してみましょう。
value_if_true: 条件がTrueのときに評価され、返される式if: 条件を導入するキーワードcondition: どちらの値が返されるかを決める真偽値の式else: 代替となる値を導入するキーワードvalue_if_false: 条件がFalseのときに評価され、返される式
他のプログラミング言語に慣れていると、この順序は少し変に見えるかもしれません。Python では「真のときの値」が先で、次に条件、そして「偽のときの値」が続きます。この順序は自然な英語のように読めます。「条件が真なら X を、そうでなければ Y をください」という形です。
さまざまな型の値を使った例をいくつか見てみましょう。
# 例1: 数値のどちらかを選ぶ
temperature = 25
comfort_level = "warm" if temperature > 20 else "cool"
print(comfort_level) # Output: warm
# 例2: 計算結果のどちらかを選ぶ
score = 85
bonus = 10 if score >= 90 else 5
print(f"Bonus points: {bonus}") # Output: Bonus points: 5
# 例3: 真偽値のどちらかを選ぶ
has_permission = True
access = "granted" if has_permission else "denied"
print(f"Access: {access}") # Output: Access: granted
# 例4: 条件は任意の真偽値式にできます
username = "admin"
role = "administrator" if username == "admin" else "regular user"
print(f"Role: {role}") # Output: Role: administrator重要な構文上の注意点
条件式では else 部分が 必須 です。if 文では else は省略できますが、ここでは両方の選択肢を提供しなければなりません。
# これは無効です - else がありません
# result = "yes" if True # SyntaxError
# これは有効です - 両方の分岐が提供されています
result = "yes" if True else "no"この要件は理にかなっています。式は常に値を生成しなければなりません。条件が False のときに else 句がなければ、その式は何の値を生成すべきでしょうか?Python は両方の可能性を明示することを求めます。
10.3) 条件式がどのように評価されるか
Python が条件式をどのように評価するかを理解すると、正しいコードを書けるようになり、プログラムが何をするかを予測できるようになります。評価は特定の、予測可能な順序に従います。
評価のプロセス
Python は条件式を次の順序で評価します。
- 条件を評価する(
ifの後ろにある真偽値式) - 結果に基づいて:
- 条件が
Trueなら、value_if_trueを評価して返す - 条件が
Falseなら、value_if_falseを評価して返す
- 条件が
重要なのは、Python は 2 つの値の式のうち 片方だけ を評価し、両方は評価しないことです。これは 短絡評価 (short-circuit evaluation) と呼ばれ、第9章で学んだ and や or 演算子の動作と似ています。
# 関係する分岐だけが評価されます
x = 10
result = x * 2 if x > 5 else x / 2
# x > 5 は True なので、Python は x * 2(20)を評価し
# x / 2 は決して評価しません
print(result) # Output: 20短絡評価が重要な理由
短絡評価はエラーを防ぎ、効率も向上させます。
# 例1: 0 での除算を回避する
denominator = 0
result = "undefined" if denominator == 0 else 100 / denominator
print(result) # Output: undefined
# 条件が True なので 100 / denominator は試行されず
# ZeroDivisionError を回避できます# 例2: None に対する操作を回避する
data = None
length = 0 if data is None else len(data)
print(length) # Output: 0
# data が None なので len(data) は呼び出されず
# TypeError を回避できます条件式における truthiness
if 文(第8章)と同様に、条件式の条件では Python の truthiness ルールが使われます。どんな値でも条件として使えます。
# 空文字列は falsy
name = ""
greeting = f"Hello, {name}" if name else "Hello, guest"
print(greeting) # Output: Hello, guest
# 空でない文字列は truthy
name = "Alice"
greeting = f"Hello, {name}" if name else "Hello, guest"
print(greeting) # Output: Hello, Alice
# 0 は falsy、0 以外は truthy
items = 0
message = "You have items" if items else "Your cart is empty"
print(message) # Output: Your cart is empty
items = 3
message = "You have items" if items else "Your cart is empty"
print(message) # Output: You have itemsネストされた評価
条件式の値は、それ自体が式(他の条件式を含む)であることもあります。Python はこれらを内側から外側へ評価します。
# value_if_true が計算式そのものの場合
age = 25
price = age * 2 if age < 18 else age * 3
print(price) # Output: 75
# 手順: age < 18 → False → age * 3 を評価 → 75
# 条件が複雑な式の場合
score = 85
grade = 90
status = "excellent" if score >= 80 and grade >= 85 else "good"
print(status) # Output: excellent
# 手順: score >= 80 → True, grade >= 85 → True
# True and True → True → "excellent" を返す10.4) 代入で条件式を使う
条件式の最も一般的な使い道の 1 つは代入です。条件に基づいて変数に 2 つの値のどちらかを設定したいときに使います。このパターンは実際のコードでも頻繁に登場します。
単純な代入パターン
条件式によって代入がよりきれいになる実用例を見てみましょう。
# 例1: 会員かどうかで割引率を設定する
is_member = True
discount = 0.15 if is_member else 0.05
print(f"Discount: {discount * 100}%") # Output: Discount: 15.0%
# 例2: 送料を決める
order_total = 45.00
shipping = 0 if order_total >= 50 else 5.99
print(f"Shipping: ${shipping:.2f}") # Output: Shipping: $5.99
# 例3: デフォルト値を設定する
user_input = "" # 空の入力をシミュレート
page_size = int(user_input) if user_input else 10
print(f"Items per page: {page_size}") # Output: Items per page: 10if 文との比較
違いを実感するために、同じ代入を if 文で書いた場合を見てみましょう。
# if 文を使う(より冗長)
is_member = True
if is_member:
discount = 0.15
else:
discount = 0.05
# 条件式を使う(よりコンパクト)
is_member = True
discount = 0.15 if is_member else 0.05どちらの方法も正しく動きますが、単に 2 つの値のどちらかを選ぶだけなら条件式のほうが簡潔です。if 文のバージョンでは 4 行が必要で、変数名 discount を 2 回繰り返しています。一方、条件式なら同じことを 1 行で実現できます。
同じロジックに基づく複数の代入
同じ条件に基づいて複数の代入を行う必要がある場合、いくつか選択肢があります。
# アプローチ1: 複数の条件式
is_premium = True
price = 99.99 if is_premium else 149.99
features = "all" if is_premium else "basic"
support = "priority" if is_premium else "standard"
# アプローチ2: 1つの if 文で複数の代入
is_premium = True
if is_premium:
price = 99.99
features = "all"
support = "priority"
else:
price = 149.99
features = "basic"
support = "standard"この場合、if 文のアプローチ(アプローチ2)のほうが読みやすいことが多いです。関連する代入がまとめて並び、それらの関係が明確になるからです。条件式のアプローチ(アプローチ1)でも動きますが、条件を 3 回繰り返しており、条件を変更する必要が出た場合に保守しにくくなることがあります。
10.5) より大きな式の中で条件式を使う
条件式は値を生成するため、より大きな式の中に埋め込めます。これにより強力でコンパクトなコードを書けますが、可読性を保つためには注意が必要です。
算術における条件式
算術演算のオペランドとして条件式を使えます。
# 条件付きの加算
base_score = 80
bonus_eligible = True
final_score = base_score + (10 if bonus_eligible else 0)
print(f"Final score: {final_score}") # Output: Final score: 90文字列フォーマットにおける条件式
条件式は f-string や他の文字列操作とも自然に組み合わせられます。
# 例1: メッセージ内の複数形
item_count = 1
message = f"You have {item_count} {'item' if item_count == 1 else 'items'}"
print(message) # Output: You have 1 item
item_count = 3
message = f"You have {item_count} {'item' if item_count == 1 else 'items'}"
print(message) # Output: You have 3 items
# 例2: 時刻に基づく条件付きの挨拶
hour = 14
greeting = f"Good {'morning' if hour < 12 else 'afternoon'}, user!"
print(greeting) # Output: Good afternoon, user!ネストされた条件式
複数の条件に対応するために条件式をネストできますが、これは控えめに行うべきです。
# 例1: 3段階の分類
score = 85
grade = "A" if score >= 90 else ("B" if score >= 80 else "C")
print(f"Grade: {grade}") # Output: Grade: B
# これを追跡してみましょう:
# score >= 90? No (85 < 90)
# そのため else 部分を評価: ("B" if score >= 80 else "C")
# score >= 80? Yes (85 >= 80)
# "B" を返す
# 例2: 温度の分類
temp = 15
category = "hot" if temp > 25 else ("warm" if temp > 15 else "cold")
print(f"Category: {category}") # Output: Category: cold
# 例3: 年齢に基づく複数段階の料金設定
age = 65
price = 0 if age < 5 else (8 if age < 18 else (12 if age < 65 else 8))
print(f"Ticket price: ${price}") # Output: Ticket price: $8ネストに関する重要な注意: ネストされた条件式は可能ですが、すぐに読みにくくなります。上の 3 つ目の例は技術的には正しいものの、理解するのが難しいです。より良い代替案については 10.7 節で議論します。
比較における条件式
比較演算の中で条件式を使えます。
# 例1: 条件付きの値との比較
base_value = 10
threshold = 15
is_large = True
result = base_value > (threshold if is_large else 5)
print(result) # Output: False
# 評価: base_value > 15 → 10 > 15 → False
# 例2: 条件付きの等価チェック
user_role = "admin"
required_role = "admin" if True else "user"
has_access = user_role == required_role
print(has_access) # Output: True10.6) 条件式 vs if 文(式 vs 文)
条件式と if 文のどちらを使うべきかを理解することは、明確で保守しやすいコードを書くうえで重要です。この違いは、Python における「式」と「文」という根本的な差にあります。
式と文: 根本的な違い
これらの用語を正確に整理しましょう。
-
式 (expression) は、値・変数・演算子・関数呼び出しの組み合わせで、Python が評価して値を生成するものです。例:
2 + 3,"hello".upper(),x if x > 0 else 0 -
文 (statement) は、アクションを実行する完全な命令です。文は値を生成しません。何かをします。例:
if x > 0: print("positive"),x = 5,for i in range(10): print(i)
# これは式です - 値(7)を生成します
result = 3 + 4
# これは文です - アクション(出力)を実行します
print("Hello")
# 条件式は式です
value = "yes" if True else "no" # "yes" を生成します
# if 文は文です
if True:
value = "yes"
else:
value = "no"
# 代入は行いますが、if 自体は値を生成しません条件式を使うべきとき
条件式が理想的なのは次のような場合です。
1. 代入で 2 つの値のどちらかを選ぶとき:
# 条件式の良い使い方
age = 16
status = "adult" if age >= 18 else "minor"
# if 文だと簡潔さに欠けます
age = 16
if age >= 18:
status = "adult"
else:
status = "minor"2. より大きな式の中でインラインに値が必要なとき:
# 良い使い方 - f-string の中で値が必要
items = 1
print(f"You have {items} {'item' if items == 1 else 'items'}")
# Output: You have 1 item
# if 文だと不格好 - 事前の代入が必要
items = 1
if items == 1:
word = "item"
else:
word = "items"
print(f"You have {items} {word}")3. ロジックがシンプルで、式が読みやすいままであるとき:
# 良い使い方 - シンプルで明快なロジック
discount = 0.15 if is_member else 0.05
max_value = a if a > b else b
sign = "positive" if x > 0 else "non-positive"if 文を使うべきとき
次のような場合は if 文を使ってください。
1. 各分岐で複数の文を実行する必要があるとき:
# if 文を使う - 各分岐で複数のアクション
if score >= 90:
grade = "A"
message = "Excellent work!"
bonus_points = 10
else:
grade = "B"
message = "Good job!"
bonus_points = 5
# 条件式だと不格好になります:
# grade = "A" if score >= 90 else "B"
# message = "Excellent work!" if score >= 90 else "Good job!"
# bonus_points = 10 if score >= 90 else 5
# (条件を不必要に繰り返します)2. 分岐が 2 つより多い(elif)とき:
# if 文を使う - 複数分岐
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
else:
grade = "F"
# ネストされた条件式は読みづらくなります:
# grade = "A" if score >= 90 else ("B" if score >= 80 else ("C" if score >= 70 else "F"))3. 分岐の片方では何もしないべきとき:
# if 文を使う - else 分岐では何もしない
if error_occurred:
print("An error occurred")
log_error(error_message)
# else は不要です
# 条件式では両方の分岐が必要です:
# result = handle_error() if error_occurred else None # 不格好並べて比較する
同じロジックを両方の方法で実装した例を見てみましょう。
# シナリオ: 送料を設定する
# バージョン1: 条件式(単純な値の選択に向いています)
order_total = 45.00
shipping = 0 if order_total >= 50 else 5.99
# バージョン2: if 文(より冗長ですが、場合によっては明快です)
order_total = 45.00
if order_total >= 50:
shipping = 0
else:
shipping = 5.99
# どちらも同じ結果になります
print(f"Shipping: ${shipping:.2f}") # Output: Shipping: $5.99この単純なケースでは、条件式のほうが簡潔で、同じくらい明確です。しかし、より複雑なシナリオを考えてみましょう。
# シナリオ: 複数ステップで注文を処理する
# バージョン1: if 文(複数のアクションに適しています)
order_total = 45.00
if order_total >= 50:
shipping = 0
discount = 0.10
message = "Free shipping applied!"
else:
shipping = 5.99
discount = 0
message = "Add $5 more for free shipping"
# バージョン2: 条件式(不格好で繰り返しが多い)
order_total = 45.00
shipping = 0 if order_total >= 50 else 5.99
discount = 0.10 if order_total >= 50 else 0
message = "Free shipping applied!" if order_total >= 50 else "Add $5 more for free shipping"ここでは if 文のほうが、関連するロジックをまとめられ、条件の繰り返しもないため、より明確です。
10.7) 条件式が可読性を高めるとき(高めないとき)
条件式は強力な道具ですが、どんな道具でも誤用されることがあります。目標は常に、正しいだけでなく、明確で保守しやすいコードを書くことです。条件式を効果的に使うためのガイドラインを見ていきましょう。
条件式が可読性を高めるとき
1. 2 つの値の間でのシンプルで明確な選択
条件式は、ロジックがストレートなときに力を発揮します。
# 素晴らしい使い方 - 非常に明確
discount = 0.20 if is_member else 0.10
# 素晴らしい使い方 - 意味が明白
status = "active" if user_logged_in else "inactive"
# 素晴らしい使い方 - シンプルな真偽の選択
can_vote = True if age >= 18 else False
# ただし、これはさらに簡単にできます: can_vote = age >= 182. 式の中でのインラインな値選択
値をインラインで必要とし、外に切り出すと不格好になるときです。
# 素晴らしい使い方 - 自然な複数形
print(f"Found {count} {'result' if count == 1 else 'results'}")
# 素晴らしい使い方 - インラインの計算調整
total = base_price * (0.9 if is_sale else 1.0)
# 素晴らしい使い方 - 条件付きのフォーマット
output = f"Status: {status.upper() if is_error else status.lower()}"3. デフォルト値の設定
条件式はフォールバック値の提供にも向いています。
# 素晴らしい使い方 - デフォルト値パターン
display_name = username if username else "Guest"
# 素晴らしい使い方 - デフォルト付きの設定
page_size = user_preference if user_preference else 25
# 素晴らしい使い方 - 安全な除算
result = total / count if count > 0 else 0条件式が可読性を損なうとき
1. ネストされた条件式
条件式をネストすると読みにくいコードになります。
# 可読性が低い - ネストされた条件式
grade = "A" if score >= 90 else ("B" if score >= 80 else ("C" if score >= 70 else "F"))
# はるかに良い - if-elif-else 文を使う
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
else:
grade = "F"if-elif-else のバージョンはすぐに理解できます。ネストされた条件式は、ロジックを理解するために慎重に読み解く必要があります。
2. 複雑な条件
条件そのものが複雑だと、条件式は読みにくくなります。
# 可読性が低い - 複雑な条件
result = "eligible" if age >= 18 and income > 30000 and credit_score > 650 and not has_bankruptcy else "not eligible"
# より良い - 明確な構造で if 文を使う
if age >= 18 and income > 30000 and credit_score > 650 and not has_bankruptcy:
result = "eligible"
else:
result = "not eligible"
# さらに良い - 条件を分解する
meets_age_requirement = age >= 18
meets_income_requirement = income > 30000
meets_credit_requirement = credit_score > 650
has_clean_record = not has_bankruptcy
if meets_age_requirement and meets_income_requirement and meets_credit_requirement and has_clean_record:
result = "eligible"
else:
result = "not eligible"3. 1 行に複数の条件式
1 行に複数の条件式を組み合わせると、次のようになります。
# 可読性が低い - 1行に詰め込みすぎ
price = base * (0.9 if is_member else 1.0) * (0.85 if is_sale else 1.0) + (0 if free_shipping else 5.99)
# より良い - ステップに分ける
member_multiplier = 0.9 if is_member else 1.0
sale_multiplier = 0.85 if is_sale else 1.0
shipping_cost = 0 if free_shipping else 5.99
price = base * member_multiplier * sale_multiplier + shipping_cost
# またはロジックが複雑なら if 文を使う
if is_member:
price = base * 0.9
else:
price = base
if is_sale:
price = price * 0.85
if free_shipping:
shipping_cost = 0
else:
shipping_cost = 5.99
price = price + shipping_cost結論
条件式は、コードをより明確に、より簡潔にできるときに使ってください。一方で、次の場合は if 文を使いましょう。
- 分岐ごとに複数の文が必要
- 分岐が 2 つより多い(
elif) - 条件やロジックが複雑
- 値の選択ではなく、副作用やアクションが必要
迷ったら、巧妙さより明確さを優先してください。コードは書かれる回数よりも読まれる回数のほうがはるかに多いので、読み手を最優先にしましょう。
条件式は、Python のツールキットにおける価値ある追加要素です。2 つの値のどちらかを選ぶときに、簡潔でエレガントなコードを書けるようになります。可読性を高める場合と、そうでない場合を理解することで、いつ条件式を使うべきかについて、より適切な判断ができるようになります。
覚えておくべき重要な原則は次のとおりです。
- 条件式は値を生成し、値が必要な場所ならどこでも使える
- 構文は
value_if_true if condition else value_if_false - Python は関係する分岐だけを評価する(短絡評価)
- 代入や式の中での単純な値の選択に最適
- 複数のアクション、複雑なロジック、2 つより多い分岐には
if文を使う - 可読性を優先する—条件式が理解しづらければ、代わりに
if文を使う
Python の学習を続けるうちに、条件式がコードを良くする場面に対して直感が身についていきます。まずは単純なケースで使う練習をし、徐々にそれが輝くパターンを見分けられるようになっていきましょう。次の章では while ループ (while loops) を扱います。これは条件に基づいてアクションを繰り返す仕組みで、このパートで身につけた判断のスキルを土台にして学んでいきます。