公開日: 2024-07-04

Pythonのmatch-caseで困ったところ

やりたかったこと

1val: int | float | bool | str = ...
2
3if (type(val) is int) or (type(val) is float):
4    ...
5elif type(val) is bool:
6    ...
7else:
8    ...

if-elseで書いた上のような処理をmatch-caseを用いてやりたいと思いました。

  • やりたかったこと
    • 型によって処理を分ける
    • 複数条件で同じ処理を実行
      • 上の例なら、valの型がintfloatで同じ処理を行う

やりたかった動機は、type(val)をいたるところに書く必要があり、コードが読みにくかったからです。

やろうとしてダメだったコード

下のコードを実行するとエラーが発生します

1val: int | float | bool | str = ...
2
3match type(val):
4    case int:
5    case float:
6        ...
7    case bool:
8        ...
9    case _:
10        ...

JavaScriptとかだったらこんな感じの書き方をしたはずですが、Pythonではダメでした。

成功するコード

1val: int | float | bool | str = ...
2
3match val:
4    case int() | float():
5        ...
6    case bool():
7        ...
8    case _:
9        ...

個人的には失敗したコードのほうが自然なんですけど、Pythonではこちらのコードが正しいらしいです。

pythonで普通にint()を実行すると0と出力されるので、val == 0でなければ中の処理が実行されなさそうですが、そんなことはなく、たとえばval == 1でもcase int():の処理が実行されます。不思議ですね。
クラスパターンというPythonの仕様だそうですが、うーんと思ってしまいました。

まとめ

💡

valがある型Classのインスタンスかどうか判定したい

  • match valとする
  • case Class():とする

💡

valがある値aまたはbであることを判定したい

  • case a | b:とする