コンテンツ

Python速習ガイド - ステップ2 制御フロー (6) - パターンマッチング (match文)

Info
  • 本講座は、Pythonプログラミングの基礎を手を動かしながら最速で身につけるための講座です。
  • 「スタイルガイド」では、Pythonできれいなコードを書くためのガイドライン(PEP8)で紹介されている内容を主に記載しています。
  • 各コードは実行して結果を確認することができます。
    ページの再読み込みで元の内容に戻りますので、自由にいじってみてください。

「ステップ2 制御フロー」の続きです。

パターンマッチングは、Python 3.10から導入された、値のパターンに基づいて条件分岐を行う機能です。

match文は、式の値を複数のパターンと照合し、一致したパターンのブロックを実行します。

match-case文
match : case パターン1: ブロック1 case パターン2: ブロック2 case _: # ワイルドカードパターン(常にマッチするデフォルトケース) デフォルトブロック
  • matchで指定した式(status_code)が順番に各caseのパターンと比較されます
  • 最初に一致したcaseのブロックのみが実行されます
  • case _:は常にマッチするデフォルトのケースで、どのパターンにもマッチしない場合に実行されます

match文では、様々な種類のパターンを使用できます。

定数値と完全一致するかどうかを確認します。

パターンに変数を使用すると、パターンに一致した値が変数に代入されます。
(この変数は対象ケースのブロック内のみで使用可能です。)

キャプチャパターンで見たように、変数は任意のパターンにマッチします。
特にその値を使用しない場合は、変数名としてアンダースコア(_)を使用します。

シーケンスパターンは、リストやタプルなど順序付きのコレクションに対して、中の要素をパターンとしてマッチングするための仕組みです。

シーケンスパターンと同様に、辞書に関してもパターンマッチングが使用可能です:

リストや辞書だけでなく、任意のクラスにパターンマッチングを行う機能もあります。
クラスに関しては本講座では未解説のため、簡単な解説を以下に記載します。

クラスとは (簡易版)

クラスとは、データとその振る舞いをまとめたデータ構造です。
例えば、2次元の点のクラスは以下のように定義できます。

上記クラスを使ったマッチングは以下のようにして書くことができます:

|(パイプ)を使用して複数のパターンを一度に指定できます。
これにより、類似したケースをまとめて扱うことができます。

パターン全体を1つの変数に代入したい場合に、asを用いたパターンが利用できます。

ORパターンと組み合わせた以下のような使い方もできます:

ifを使用して追加の条件を指定できます。
match文で使用される if <条件式> の部分をガードといいます。

変数の値を使用したパターンマッチングに注意

「キャプチャパターン」で見た通り、match 文の case で変数名を指定すると、その変数にマッチ対象の値が代入されます。

たとえば、次のようなコードは一見、定数(NOT_FOUND)と比較しているように見えますが、
実際にはmatch文内でNOT_FOUNDという新しい変数を作成して値を代入しています:

意図した動作を行うには、ガード(if)を使用して値を比較します:

Python 3.10で導入されたmatch文は、値のパターンに基づいて条件分岐を行う強力な機能です。

match文の主な特徴:

  • 式の値を複数のパターンと照合し、一致したパターンのブロックを実行
  • パターンは上から順に評価され、最初に一致したパターンのみが実行される
  • 柔軟なパターン記述により、複雑な条件分岐をシンプルに表現可能
  • if-elif-elseによる条件分岐よりも、データ構造に対する処理を直感的に記述できる

パターンの種類:

カテゴリ パターン 説明
基本的なパターン リテラルパターン 定数値と完全一致 case 200:
キャプチャパターン マッチした値を変数に代入 case value:
ワイルドカードパターン 任意の値にマッチ(_ case _:
構造に関するパターン シーケンスパターン リストやタプルの構造マッチング case [x, y]:
マッピングパターン 辞書の構造マッチング case {"name": name}:
クラスパターン オブジェクトの属性マッチング case Point(x=0, y=y):
修飾付きパターン ORパターン 複数パターンの選択 case "A" | "B":
ASパターン マッチ対象全体を変数に割当 case (x, y) as point:
ガード付きパターン 追加条件を指定 case x if x > 0:
📚練習問題1: シンプルなゲームコマンド処理

プレイヤーの入力コマンドに応じて処理を行うゲームシステムを作りましょう。
今回は各コマンドに対して、指定された文字列を出力するプログラムにします。

コマンドは以下の形式で与えられます:

  • 移動コマンド: ["move", <方向>, <歩数>] (例: ["move", "north", 5]
    • => 「<方向>方向に<歩数>歩移動します」
  • 攻撃コマンド: ["attack", <武器>] (例: ["attack", "sword"]
    • => 「<武器>で攻撃します」
  • アイテム使用: ["use", <アイテム>] (例: ["use", "potion"]
    • => 「<アイテム>を使用します」
  • ヘルプ表示: ["help"]
    • => 「ヘルプメニューを表示します」
  • ゲーム終了: ["quit"] または ["exit"]
    • => 「ゲームを終了します」
  • その他のコマンド
    • => 「無効なコマンドです」

match文を使って、各コマンドに対応するメッセージを表示するコードを書きましょう。

解答例
📚練習問題2: 天気予報システム

天気データ(天気と気温のタプル)に基づいて、適切な服装のアドバイスを表示するシステムを作りましょう。

  • "雨" かつ 10℃ 未満 => 「雨が降っています。レインコートを着用しましょう。」
  • "雨" かつ 10℃ 以上 => 「雨が降っています。傘を忘れずに持っていきましょう。」
  • "雪" => 「雪が降っています。厚手のコートと手袋を着用しましょう。」
  • "晴れ" または "曇り" かつ 30℃ 以上 => 「天気は<天気>で気温が高いです(<気温>℃)。半袖を着用しましょう。」
  • "晴れ" かつ 15℃未満 => 「晴れていますが気温が低めです(<気温>℃)。上着を持っていきましょう。」
  • "曇り" かつ 15℃未満 => 「曇りで肌寒いです(<気温>℃)。ジャケットを着用しましょう。」
  • その他 => 「<天気><気温>℃です。季節にあった服装をしましょう。」
解答例
📚練習問題3: ショッピングカート処理

ショッピングカートの商品リストに対して、パターンマッチングを使って合計金額を計算しましょう。
ただし、商品リストは (商品名, 数量) または (商品名, 数量, 割引率) という形のタプルです。

解答例

関連記事