Pythonのmatch case(match文)で複数条件を処理する方法
Pythonの構造的パターンマッチング(match-case文)では、複数の条件を簡潔に処理できます。この機能はPython 3.10から導入され、if-elif-else文より複雑な条件分岐をわかりやすく書ける利点があります。match文は値を受け取り複数のcase節と照合し、最初にマッチしたパターンのコードブロックを実行します。
match-case文の構文は値をパターンと比較するシンプルなものですが、複数のパターンを扱う方法も用意されています。特にパイプ記号(|)を使うと、一つのcaseで複数の値に対応できるため、コードの冗長を減らせます。
【サンプルコード】
# 基本的なmatch-caseの使用例(複数条件)
def check_status(status):
match status:
case "ready" | "prepared" | "standby":
return "システムは準備完了です"
case "running" | "processing":
return "システムは実行中です"
case "error" | "failed" | "crashed":
return "システムはエラーが発生しています"
case _:
return "未知の状態です"
# 複数のステータスでテスト
statuses = ["ready", "processing", "failed", "unknown"]
for status in statuses:
print(f"ステータス '{status}': {check_status(status)}")
【実行結果】
ステータス 'ready': システムは準備完了です
ステータス 'processing': システムは実行中です
ステータス 'failed': システムはエラーが発生しています
ステータス 'unknown': 未知の状態です
行番号 | 詳細説明 |
---|---|
2行目 | check_status関数を定義 |
3行目 | match文でstatusを判定開始 |
4行目 | ready prepared standbyをcaseでまとめて処理 |
5行目 | マッチした場合の戻り値をreturn |
6行目 | running processingをcaseでまとめて処理 |
7行目 | マッチした場合の戻り値をreturn |
8行目 | error failed crashedをcaseでまとめて処理 |
9行目 | マッチした場合の戻り値をreturn |
10行目 | どのcaseにもマッチしない場合をcase _で指定 |
11行目 | 未知の状態を示す戻り値をreturn |
14行目 | statusesリストにテスト用のステータスを代入 |
15行目 | statusesをループで取り出す |
16行目 | ステータスとcheck_statusの結果をprint |
【PR】『Python』を学べる企業・個人向けのプログラミングコース
match caseで複数のデータ型に対応する方法
match-case文は単純な値の比較だけではなく、リストやタプル、辞書など複数のデータ型にも対応できるため、データの型と内容に応じた分岐をまとめやすくなります。特にOR条件とasキーワードを組み合わせると、似たような型に一度に対応できるので便利です。
複合データ型の場合、アンパック演算子(*)で可変長の要素に対応したり、辞書の特定のキーだけを取り出したりすることもできます。これらを組み合わせると、複雑な構造を扱う際のコードをわかりやすく書けます。
【サンプルコード】
# 複数のデータ型に対応するmatch-case
def process_data(data):
match data:
case str(s):
return f"文字列: {s}の長さは{len(s)}文字です"
case list() | tuple() as sequence:
return f"シーケンス: 要素数は{len(sequence)}です"
case {"name": name, "age": age}:
return f"ユーザー: {name}さん({age}歳)"
case {"type": "point", "x": x, "y": y}:
return f"座標点: ({x}, {y})"
case _:
return "未知のデータ型です"
# 様々なデータ型でテスト
test_data = [
"Python",
[1, 2, 3, 4],
(10, 20, 30),
{"name": "田中", "age": 30},
{"type": "point", "x": 5, "y": 10},
{"other": "data"}
]
for data in test_data:
print(process_data(data))
【実行結果】
文字列: Pythonの長さは6文字です
シーケンス: 要素数は4です
シーケンス: 要素数は3です
ユーザー: 田中さん(30歳)
座標点: (5, 10)
未知のデータ型です
行番号 | 詳細説明 |
---|---|
2行目 | process_data関数を定義 |
3行目 | match文でdataを判定開始 |
4行目 | dataが文字列のときの処理 |
5行目 | マッチした文字列の長さ情報を返す |
6行目 | dataがlistまたはtupleのときの処理 |
7行目 | マッチしたシーケンスの要素数を返す |
8行目 | dataが辞書でnameとageキーを持つときの処理 |
9行目 | マッチした場合のユーザー情報を返す |
10行目 | dataが辞書でtypeがpointのときの処理 |
11行目 | 座標点の情報を返す |
12行目 | どのパターンにも当てはまらない場合の処理 |
14行目 | テストデータをリストでまとめて定義 |
23行目 | process_dataの結果をprint |
match caseで複数変数を抽出する方法
match-case文では、複雑な構造から複数の変数を同時に抽出できます。ネストされたリストや辞書の特定要素を一括で取り出せるため、データ検証と同時に処理を進めやすいです。
例えばリストの要素数や辞書の特定キーをチェックしながら変数に代入する場合、if文を多用するよりもコードがすっきりするため、大きなJSONやAPIレスポンスを扱うときにも便利です。
【サンプルコード】
# 複数変数を抽出するmatch-case
def analyze_command(command):
match command:
case ["GET", path]:
return f"GETリクエスト: パス '{path}' にアクセスします"
case ["POST", path, {"content": content, "type": type}]:
return f"POSTリクエスト: パス '{path}' に {type} 形式で '{content}' を送信します"
case ["DELETE", path, id]:
return f"DELETEリクエスト: パス '{path}' のID '{id}' を削除します"
case ["UPDATE", path, id, {"fields": fields}]:
return f"UPDATEリクエスト: パス '{path}' のID '{id}' を更新します。フィールド: {fields}"
case _:
return "無効なコマンドです"
# 様々なコマンドでテスト
commands = [
["GET", "/api/users"],
["POST", "/api/comments", {"content": "素晴らしい記事です", "type": "text/plain"}],
["DELETE", "/api/posts", "12345"],
["UPDATE", "/api/profile", "user123", {"fields": ["name", "email"]}],
["INVALID", "command"]
]
for cmd in commands:
print(analyze_command(cmd))
【実行結果】
GETリクエスト: パス '/api/users' にアクセスします
POSTリクエスト: パス '/api/comments' に text/plain 形式で '素晴らしい記事です' を送信します
DELETEリクエスト: パス '/api/posts' のID '12345' を削除します
UPDATEリクエスト: パス '/api/profile' のID 'user123' を更新します。フィールド: ['name', 'email']
無効なコマンドです
行番号 | 詳細説明 |
---|---|
2行目 | analyze_command関数を定義 |
3行目 | match文でcommandを判定開始 |
4行目 | GETコマンドの場合の処理 |
5行目 | マッチした場合の文字列をreturn |
6行目 | POSTコマンドの場合の処理 |
7行目 | マッチしたときにPOST内容をreturn |
8行目 | DELETEコマンドの場合の処理 |
9行目 | IDを取得してメッセージをreturn |
10行目 | UPDATEコマンドの場合の処理 |
11行目 | フィールド情報を含めてreturn |
12行目 | その他のコマンドは無効と返す |
14行目 | テストコマンドをリストにまとめる |
20行目 | analyze_commandで処理して結果をprint |
【PR】『Python』を学べる個人・中高生向けのプログラミングコース
match caseでガード節を使用した複数条件を処理する方法
match-case文にはガード節を追加する機能があります。case パターン if 条件
の形式で書くと、パターンにマッチした後でさらに条件式を評価できるため、範囲チェックなど複雑な条件をまとめやすくなります。
ガード節はネストの深いif文を書くよりも意図が明確で読みやすいです。複数の型や値に対して、同様の条件を設定したいときにも便利に使えるでしょう。
【サンプルコード】
# ガード節を使用したmatch-case
def categorize_number(n):
match n:
case int() | float() as num if num < 0:
return f"{num}は負の数です"
case int() as num if num == 0:
return "ゼロです"
case int() as num if num > 0 and num % 2 == 0:
return f"{num}は正の偶数です"
case int() as num if num > 0:
return f"{num}は正の奇数です"
case float() as num if num > 0:
return f"{num}は正の小数です"
case _:
return "数値ではないか、想定外の数値です"
# 年齢と権限によるアクセス制御の例
def check_access(user):
match user:
case {"role": "admin"}:
return "管理者権限でアクセスが許可されています"
case {"role": "user", "age": age} if age >= 18:
return "成人ユーザーとしてアクセスが許可されています"
case {"role": "user", "age": age} if age < 18:
return "未成年ユーザーには一部コンテンツが制限されています"
case {"role": role}:
return f"未知の役割: {role}"
case _:
return "ユーザー情報が不完全です"
# テスト用データ
numbers = [-10, 0, 7, 22, 3.14, "string"]
users = [
{"role": "admin", "name": "管理者", "age": 35},
{"role": "user", "name": "一般ユーザー1", "age": 25},
{"role": "user", "name": "一般ユーザー2", "age": 16},
{"role": "guest"},
{"name": "不完全なユーザー"}
]
print("--- 数値の分類 ---")
for n in numbers:
print(f"{n}: {categorize_number(n)}")
print("\n--- アクセス制御 ---")
for user in users:
print(f"{user}: {check_access(user)}")
【実行結果】
--- 数値の分類 ---
-10: -10は負の数です
0: ゼロです
7: 7は正の奇数です
22: 22は正の偶数です
3.14: 3.14は正の小数です
string: 数値ではないか、想定外の数値です
--- アクセス制御 ---
{'role': 'admin', 'name': '管理者', 'age': 35}: 管理者権限でアクセスが許可されています
{'role': 'user', 'name': '一般ユーザー1', 'age': 25}: 成人ユーザーとしてアクセスが許可されています
{'role': 'user', 'name': '一般ユーザー2', 'age': 16}: 未成年ユーザーには一部コンテンツが制限されています
{'role': 'guest'}: 未知の役割: guest
{'name': '不完全なユーザー'}: ユーザー情報が不完全です
行番号 | 詳細説明 |
---|---|
2行目 | categorize_number関数を定義 |
3行目 | match文でnを判定開始 |
4行目 | intまたはfloatで負の数の場合を処理 |
5行目 | マッチした場合に負の数を示す文字列をreturn |
6行目 | nがintでゼロの場合を処理 |
7行目 | マッチした場合にゼロを示す文字列をreturn |
8行目 | nが正の偶数の場合を処理 |
9行目 | マッチした場合に正の偶数を示す文字列をreturn |
10行目 | nが正の奇数の場合を処理 |
11行目 | マッチした場合に正の奇数を示す文字列をreturn |
12行目 | nがfloatで正の数の場合を処理 |
13行目 | マッチした場合に正の小数を示す文字列をreturn |
14行目 | どのパターンにも合致しない場合を処理 |
18行目 | check_access関数を定義 |
19行目 | match文でuserを判定開始 |
20行目 | roleがadminの場合を処理 |
21行目 | アクセス許可を示す文字列をreturn |
22行目 | roleがuserでageが18以上の場合を処理 |
23行目 | 成人ユーザーのアクセス許可をreturn |
24行目 | roleがuserでageが18未満の場合を処理 |
25行目 | 未成年ユーザーで制限ありをreturn |
26行目 | 未知の役割を処理 |
27行目 | ユーザー情報が不完全な場合をreturn |
31行目 | numbersにテスト用の値を用意 |
32行目 | usersにテスト用ユーザー情報を用意 |
38行目 | numbersをループしてcategorize_numberの結果をprint |
40行目 | アクセス制御の結果をprint |
※上記コンテンツの内容やソースコードはAIで確認・デバッグしておりますが、間違いやエラー、脆弱性などがある場合は、コメントよりご報告いただけますと幸いです。
ITやプログラミングに関するコラム
- 【Python】@(アットマーク)の意味を簡単に解説
- 【Python】オブジェクト指向を使わないで設計する方法
- 【Python】リスト(list)内包表記におけるifやif elseなどの使い分け
- 【Python】venvのバージョン(version)指定や確認方法