初心者のためのDjango入門
■第23話:Pythonのmatch文
(最終更新日:2024.11.04)
(絵が小さい場合はスマホを横に)
「match文で条件判定を簡単に!」
Python3.10になって、新たな機能としてmatch文が使えるようになった。
matchはswitchと似たような構文である。
switchは、C言語やJavaScriptで使われるメジャーな構文であるが、Pythonでは近年matchを採用した。
今回は、他の言語でよく使われるswitch文との違いを踏まえて、Pythonのmatch文について解説する。
[目次]
1.switch文との違い
Python自体にはswitch文は無いので、ここではJavaScriptのswitch文と比較する。
JavaScriptのswitch文は、ある変数や式の値に基づいて分岐し、case句の中では文字列や定数のみをサポートする。
つまり、文字列や数値の一致を連続的に判定するのが一般的なswitch文になる。
下記では、valueの値がAかB、その他であるかを判定できる。判定したら、consoleにその結果を表示する。
breakを書くことで、当てはまったcase以降のcase判定を飛ばし、switch文を抜けることができる。
JavaScriptのswitch文
Pythonのmatch文は幾つか違いがある。パターンマッチングとして、文字列や定数に加え、シーケンス、データ構造までサポートしている。
シーケンス、データ構造のマッチングの例は、次項以降で説明する。
他にもswitch文との違いとしては、JavaScriptの例で示したdefaultがないことが挙げられる。
先ほどのJavaScriptのswitch文と同じ動きをするものを下記に示す。match文にdefaultという命令は無いので、case _という記述で代用している。
また、JavaScriptのswitch文(上記)では明示的にbreakを入れないとswitch文を抜けることができないが、
Pythonのmatch文(下記)では、matchしたcase文のみが実行され、match文を抜けるという特徴がある。
まずは、この辺りの違いを確実に抑えておこう。
Pythonのmatch文
2.シーケンスマッチ
ここでは、Pythonのmatch文の長所とも言える、シーケンスマッチについて説明する。
これは、switch文では対応していない機能である。
Pythonのmatch文において、シーケンスをサポートするというのは、
リストやタプルなどのシーケンス型のデータ構造を扱う際の柔軟なパターンマッチングが可能であることを意味する。
以下に、シーケンスに関するパターンマッチングの例を示す。
下記は、Pythonのリストの長さで条件分岐するmatch文である。
最初のcaseでは空である事を判定し、2番目のcaseでは一個要素があることを判定、
3番目のcaseでは2個要素があることを判定している。
4番目のcaseでは、3個以上要素があることを判定したいが、case文の書き方だけでは
要素が3個以上のリストであることと、リスト以外のデータであることを区別できない。
そこはif文の判定で、listのデータかそれ以外かを見分け、listであれば3個以上要素を持っていることを判断している。
リストの長さマッチ
また、要素の中身についてもmatch文で判定できる。 最初のcaseでは、一番目の要素が1であるかを判定している。 それにより、(最初の要素が1なので)1つめのprint文ではTrueを出力し、(最初の要素が1ではないので)2つめのprint文ではFalseを出力している。
リストの最初の要素が1であるか
このように、*_を用いることで、2番目以降の要素はワイルドカードになり、最初の要素が1であるかを判定している。
同様に最後の要素が何であるかを示すには「case [*_ , 1]:」という書き方で判定できる。「case [*_ , 1, 2, 3]:」という連続的な要素の中身判定もできる。
ただし、注意点としては「case [*_ , 1, 2, 3, *_]:」という書き方で、間の要素が何であるかという判定はできない。2個以上ワイルドカード(*)を使うことができないからだ。
ちなみに、タプルに関しても同様にシーケンスマッチを使うことができる。
非常に便利な書き方なので、覚えておこう。
3.データ構造マッチ
データ構造のマッチング判定は、特定のデータ構造やその構造内の要素が、定義されたパターンや条件に合致するかどうかを評価する。
Pythonのmatch文は、このデータ構造のマッチングを効率的に行う機能を提供する。
まずはタプルの例を取り上げる。下記のタプルのマッチング判定では、
タプルの中の2個の要素の中身がint型であるか、2個の要素を持つタプルか、それ以外かを見ている。
print文に書かれた一つ目のタプルでは、タプルの中の2個の要素の中身がint型であることを示し、
print文に書かれた二つ目のタプルでは、int型ではない2個の要素を持つタプルであることを示している。
タプルのマッチング
次にリストの例を取り上げる。 下記のリストのマッチング判定では、 空のリストであるか、最初の要素がint型であるリストか、それ以外かを見ている。 print文に書かれた一つ目のリストは、空のリストであることを示し、 print文に書かれた二つ目のリストでは、最初の要素がint型であるリストを示している。
リストのマッチング
次に辞書の例を取り上げる。 下記の辞書のマッチング判定では、 nameがkeyの値が文字列型、ageがkeyの値がint型の辞書であるかどうかを見ている。 print文に書かれた一つ目の辞書は、nameがkeyの値が文字列型、ageがkeyの値がint型の辞書であることを示し、 print文に書かれた二つ目、三つ目の辞書では、それ以外の辞書であることを示している。
辞書のマッチング
最後にClassの例を取り上げる。 下記のClassのマッチング判定では、 コンストラクタのnameの値が文字列型、ageの値がint型かどうかを見ている。 print文に書かれたaliceインスタンスは、nameの値が文字列型、ageの値がint型の辞書であることを示している。 そして、一個目のcaseにマッチするため「Person named Alice aged 30」 をprint文で出力している。
Classのマッチング
4.まとめ
今回はPython3.10から搭載されたmatch文について解説した。 match文はswitch文と同じような使い方だけでなく、データ構造やデータの型、内容について判定することができる。 今回のmatch文の登場により、if文ではまとまりにくい、複雑な条件分岐があった場合でも、スマートに判定ができるようになった。 単純な変数の値だけでなく、リスト、タプル、辞書、クラスの中身を判別したいときは、ぜひPythonのmatch文を使ってみよう。
▼参考図書、サイト
日経ソフトウエア 2023年9月号 日経BP
Python 3.10の新機能(その1) パターンマッチ python Japan
Python3.10の新機能(2) - Pythonにmatch文がやってくる Qiita