Pythonでプログラミングを行う際、避けては通れないのが条件分岐の処理です。

特に実務的なアプリケーション開発では、単一の条件だけでなく「AかつB」「CまたはD」といった複数の条件を組み合わせて判定するシーンが頻繁に登場します。

しかし、安易にif文を重ねるとコードの可読性が著しく低下し、バグの温床となる「スパゲッティコード」を招きかねません。

2026年現在、Python 3.10で導入されたmatch-case文の活用も定着し、より洗練された条件分岐の記述が可能になっています。

本記事では、Pythonのif文における複数条件の基本から、最新のmatch-caseを用いた構造的な記述、さらにはコードをスッキリ見せるためのテクニックまで、実戦で役立つ知識を詳しく解説します。

複数条件を指定する基本:論理演算子(and, or, not)

Pythonのif文で複数の条件を組み合わせる際、最も基本となるのが論理演算子です。

これらを使用することで、複雑な論理構造を1つのif文、あるいは簡潔な階層構造で表現できます。

and演算子(論理積)

and演算子は、指定したすべての条件が真(True)である場合にのみ、全体の評価を真とします。

Python
# 数値が範囲内かつ偶数かどうかを判定
age = 25
has_license = True

if age >= 18 and has_license:
    print("運転資格があります。")
else:
    print("運転資格がありません。")
実行結果
運転資格があります。

or演算子(論理和)

or演算子は、指定した条件のうち少なくとも1つが真(True)であれば、全体の評価を真とします。

Python
# 週末または祝日かどうかを判定
day = "Saturday"
is_holiday = False

if day == "Saturday" or day == "Sunday" or is_holiday:
    print("休業日です。")
else:
    print("営業日です。")
実行結果
休業日です。

not演算子(論理否定)

not演算子は、条件の真偽を反転させます。

条件が偽(False)であることを判定したい場合に有効です。

Python
# リストが空でないことを確認
items = []

if not items:
    print("アイテムがありません。")
実行結果
アイテムがありません。

優先順位と可読性を高める括弧の使い方

複数の論理演算子を組み合わせる場合、演算子には評価される優先順位があることに注意が必要です。

Pythonでは、優先順位が高い順に notandor となっています。

意図しない判定を防ぐための括弧

以下の例では、括弧の有無によって結果が異なります。

Python
# 優先順位の例
is_admin = False
has_permission = True
is_owner = True

# 括弧なし: (is_admin and has_permission) or is_owner として評価される
if is_admin and has_permission or is_owner:
    print("アクセス許可(1)")

# 意図的に順序を変える場合
if is_admin and (has_permission or is_owner):
    print("アクセス許可(2)")
実行結果
アクセス許可(1)

上記の結果において、アクセス許可(2)は出力されません。

これは is_admin が False であるため、後半の括弧内が True であっても and の評価で全体が False になるからです。

複雑な条件を記述する際は、計算の順序を明示するために括弧を使用することを強く推奨します。

これにより、自分以外の開発者がコードを読んだ際の誤解を防ぐことができます。

効率的な複数条件の記述パターン

Pythonには、if文を連ねる以外にも、複数条件をスマートに記述する方法がいくつか用意されています。

比較演算子の連鎖

数値の範囲を判定する場合、Pythonでは数学の不等式のように比較演算子を連鎖させることができます。

Python
score = 85

# andを使わずに書ける
if 80 <= score < 90:
    print("評価:B")
実行結果
評価:B

この書き方は、score >= 80 and score < 90 と同じ意味ですが、より直感的で読みやすいコードになります。

in演算子による複数候補の判定

特定の変数が「複数の候補のいずれかに一致するか」を判定する場合、or を繰り返すのではなく in 演算子を使うのが効率的です。

Python
user_role = "editor"
allowed_roles = ["admin", "editor", "manager"]

if user_role in allowed_roles:
    print("編集権限があります。")
実行結果
編集権限があります。

all() と any() 関数の活用

判定すべき条件がリストやイテラブルなオブジェクトとして存在する場合、all()any() 関数を使うとコードが劇的にスッキリします。

関数説明
all(iterable)すべての要素が真であれば真
any(iterable)いずれかの要素が真であれば真
Python
conditions = [
    len("password123") >= 8,
    any(c.isdigit() for c in "password123"),
    any(c.isupper() for c in "password123")
]

if all(conditions):
    print("強固なパスワードです。")
else:
    print("パスワードの強度が不足しています。")
実行結果
パスワードの強度が不足しています。

Python 3.10以降の標準:match-case文による構造化

Python 3.10以降、構造的パターンマッチング(match-case)が導入されました。

これは従来の他言語におけるswitch文に近いものですが、より強力なデータ構造の解析機能を備えています。

複数条件の分岐が複雑になる場合、if-elifの羅列よりもmatch-caseの方が可読性が高まります。

基本的なmatch-case

複数の値を一度に判定したり、条件をパターンとして抽出したりすることが可能です。

Python
def check_status(status_code):
    match status_code:
        case 200 | 201:
            return "成功"
        case 400 | 404:
            return "クライアントエラー"
        case 500:
            return "サーバーエラー"
        case _:
            return "不明なステータス"

print(check_status(404))
実行結果
クライアントエラー

match-case内でのガード条件(if)

match-caseの中では、各caseに対してさらに if 文(ガード句)を付与することで、パターンの合致+詳細条件という二段構えの判定が行えます。

Python
point = (10, 20)

match point:
    case (x, y) if x == y:
        print(f"原点を通る直線上の点: ({x}, {y})")
    case (x, y) if x > 0 and y > 0:
        print(f"第一象限の点: ({x}, {y})")
    case _:
        print("その他の点")
実行結果
第一象限の点: (10, 20)

条件分岐のネストを避ける「ガード句」のテクニック

複数条件を扱う際、初心者が陥りやすいのが「if文の中にif文を入れる」というネスト(入れ子)構造です。

ネストが3段階、4段階と深くなると、コードのロジックを追うのが非常に困難になります。

これを解消するのがガード句(Early Return / Early Continue)という考え方です。

ネストが深い例(非推奨)

Python
def process_data(data):
    if data is not None:
        if len(data) > 0:
            if "target" in data:
                # 本来やりたい処理
                print("処理実行")

ガード句を用いた例(推奨)

「条件に合致しない場合はすぐに処理を抜ける」という書き方に変えるだけで、メインのロジックがインデントの浅い場所に配置されます。

Python
def process_data(data):
    # 条件に合わないものを先に排除
    if data is None:
        return
    if len(data) == 0:
        return
    if "target" not in data:
        return
    
    # メイン処理
    print("処理実行")

この手法は、2026年現在のソフトウェア開発においても「クリーンコード」の基本として重要視されています。

パフォーマンスと安全性のための短絡評価(Short-circuit Evaluation)

Pythonの論理演算子には短絡評価という特性があります。

これは、全体の評価結果が確定した時点で、それ以降の条件式の評価をスキップする仕組みです。

  • and演算子:左側の式が False なら、右側の式は無視される。
  • or演算子:左側の式が True なら、右側の式は無視される。

これを活用すると、エラーを未然に防ぐ記述が可能です。

Python
# リストが存在し、かつ最初の要素が特定の値かチェック
# リストがNoneの場合、本来は len() でエラーになるが、短絡評価により回避される
items = None

if items is not None and len(items) > 0:
    print("アイテムが存在します")
else:
    print("条件を満たしません")
実行結果
条件を満たしません

もし items is not None というチェックがない状態で len(items) を実行すると、TypeError が発生してプログラムが停止してしまいます。

短絡評価を意識することは、堅牢なプログラムを書く上で欠かせないテクニックです。

辞書(dict)を用いた条件分岐の動的処理

if文が非常に多くなる場合、条件と処理を「辞書」として定義することで、コードを動的かつ簡潔に保つことができます。

これは、特定の値に応じて異なる関数を実行したい場合に特に有効です。

Python
def save_file():
    return "保存しました"

def delete_file():
    return "削除しました"

def default_action():
    return "該当するアクションがありません"

# アクションに応じた関数をマッピング
actions = {
    "save": save_file,
    "delete": delete_file
}

user_input = "save"
# 辞書のgetメソッドを使い、該当がない場合はdefault_actionを実行
result = actions.get(user_input, default_action)()
print(result)
実行結果
保存しました

このように、条件そのものをデータとして扱うことで、プログラムの拡張性が向上します。

新しい条件が増えても if-elif を増設する必要がなく、辞書に要素を追加するだけで対応可能になります。

まとめ

Pythonにおけるif文の複数条件の扱いは、単なる構文の知識を超えて、コードの品質を左右する重要な要素です。

本記事で解説した以下のポイントを振り返りましょう。

  • 論理演算子(and, or, not)を基本とし、括弧を使って優先順位を明示する。
  • 数値範囲の連鎖比較や in 演算子を活用して簡潔に記述する。
  • 大量の条件は all()any() で整理する。
  • 複雑なパターンマッチングには Python 3.10+ の match-case を導入する。
  • ネストを深くしないために ガード句 を積極的に活用する。
  • 短絡評価を理解し、エラーに強いコードを書く。

これらのテクニックを状況に応じて使い分けることで、2026年のモダンな開発環境にふさわしい、メンテナンス性の高いPythonコードを記述できるようになります。

まずは自身のコードを見直し、深いネストや冗長な条件式をリファクタリングすることから始めてみてください。