Pythonでswitch-case文を使いたい、という要望は昔から上がっていました。(特にPython2時代を知るエンジニアたちから)
多くの議論がされ、Python 3.10でついに実装されたのがmatch構文です。
それまで、if/elifで対応され続けてきた、複雑な条件分岐をすっきり書くようになったという大きな進化です。
このコンテンツでは、可読性の高いPythonの機能であるmatch文の使い方を紹介します。
Pythonのmatch文とは
Pythonにおけるmatchとは、PEP(Pythonにおける機能改善の設計書)においてPEP634で定義されたPython 3.10の新機能でした。
多くのプログラミング言語で実装されているパターンマッチング構文ですが、Pythonはif-elif-elseを利用した限定的な書き方しかなかったことから生まれました。
match文によって、よりクリーンで可読性の高いPythonコーディングができるようになったという革新的な機能です。
matchの基本
まずはmatchの書き方の構造を見てみましょう。
match 変数:
case パターンA:
return 返り値A
case パターンB:
return 返り値B
case パターンC:
return 返り値C
case _:
return デフォルト値上記のように、すっきりした書き方ができます。
とある変数に対して、どういった値で渡されたかによって中の構文を切り替えられます。(上記の例だとパターンごとにreturnしています)
matchを使った簡単な例
簡単な実装例を見てみましょう。
def animal_says(animal: str) -> str:
match animal:
case "dog":
return "わんわん!"
case "cat":
return "にゃーん!"
case "duck":
return "ぐわっ!"
case _:
return "おっす!"
if __name__ == "__main__":
print(animal_says("dog"))
print(animal_says("cat"))
print(animal_says("duck"))
print(animal_says("cow"))このスクリプトを実行すると、以下のような出力結果が得られます。
$ python match.py
わんわん!
にゃーん!
ぐわっ!
おっす!ご覧のように、animalという変数に対してマッチした結果が返ってきました。
matchとif-elseの比較
先ほどの例をif-elseで表現してみます。
def animal_says(animal: str) -> str:
if animal == 'dog':
return "わんわん!"
elif animal == 'cat':
return "にゃーん!"
elif animal == 'duck':
return "ぐわっ!"
else:
return "おっす!"
if __name__ == "__main__":
print(animal_says("dog"))
print(animal_says("cat"))
print(animal_says("duck"))
print(animal_says("cow"))上記のように、animal ==を何度も書かなくて済むので省コード化されます。この程度であれば、if-elseでもいい、と感じる人もいるでしょうが、これがより多くの条件を含めば含むほどmatchが効果を発揮します。
matchの実用的な使用例
簡単な実装例だけでちょっとしたマッチングパターンは綺麗に実装できますが、これをもう少し発展させてみましょう。
計算式でパターンマッチング
まず、アンチパターンになりますが、計算式を条件にしたい場合はif-elif-elseを使うほうが良いでしょう。
以下に例を示します。
from typing import List, Tuple
def num_lists(nums: List[int]) -> Tuple[List[int], List[int], List[int]]:
even = []
one_third = []
others = []
for i in nums:
match i:
case i if i % 2 == 0:
even.append(i)
case i if i % 3 == 0:
one_third.append(i)
case _:
others.append(i)
return even, one_third, others
if __name__ == '__main__':
[print(l) for l in num_lists(range(10))]計算式をcaseに含めたい場合は上記のようにi if i % == 0のように内部で変数化が必要なため、冗長な表現になってしまいます。
クラスでパターンマッチング
続いて、クラスによるパターンマッチングの例です。
class Human:
has_philosophy: bool
class Animal:
has_instinct: bool
def indentify(x):
match x:
case Human():
return "Human"
case Animal():
return "Animal"
case _:
return "Unknown"
if __name__ == "__main__":
obj = Human()
obj.has_philosophy = True
print(f'I am a {indentify(obj)}')
obj = Animal()
obj.has_instinct = True
print(f'I am an {indentify(obj)}')
print(f'I am an {indentify(0)}')上記の出力結果は以下です。
$ python match.py
I am a Human
I am an Animal
I am an Unknown特定の変数がどのクラスオブジェクトかを判定できます。通常、if-elseでクラスを判定するためにはisinstance()を使いますが、その冗長さを回避できます。
matchでクリーンなコードを書こう
ここまで、Pythonのmatch文を見てきましたが、連なりすぎるif-else文はそもそものコード設計に難ありなことが多いです。
ですので、matchを使うこと自体がおかしいのでは、と見直すこともありますが、ゲームシステムのような多くのクラスを有するプロジェクトでは使う機会があるでしょう。
プロジェクトが肥大化すればするほど、クリーンなコードが求められることなるので、ぜひこの機会に使い方を覚えて有効活用していきましょう。





