Open1
ユニオン型の変数をタプルにしてパターンマッチさせるとmypyではエラーになる件
以下のサンプルコードのようなものを書いたら mypy チェックでエラーになった。mypy はエラーになるがコードとして実行は可能。
バージョン: python3.11.9, mypy 1.10.0
サンプルコード:
def check(left: int | None, right: int | None) -> str:
match left, right:
case None, None:
return "Both None"
case _, None:
return "Right is None"
case None, _:
return "Left is None"
case l, r if l == r:
return "Equal"
case l, r if l < r: # ここでエラー、 int と推論してくれない
return "Right is higher than left"
case _:
return "Left is higher than right"
vscode拡張の mypy-type-checker のエディタ上で出たエラーメッセージ:
Unsupported operand types for < ("int" and "None")
Unsupported operand types for > ("int" and "None")
Both left and right operands are unionsMypy
Unsupported left operand type for < ("None")
https://github.com/python/mypy/issues/15426#issuecomment-1589505882 によると mypy の仕様らしく、pyright ではこれはエラーにならないとのこと。
mypy と pyright では型の扱いの思想が違うらしい。
やりたいことのイメージを Scala で書くと以下(ChatGPT製)
def describe(a: Option[Int], b: Option[Int]): String = (a, b) match {
case (None, None) => "Nothing"
case (Some(x), None) => x.toString
case (None, Some(y)) => y.toString
case (Some(x), Some(y)) => s"$x and $y"
}
// 使用例
val result1 = describe(Some(3), None) // "3"
val result2 = describe(None, Some(5)) // "5"
val result3 = describe(None, None) // "Nothing"
val result4 = describe(Some(2), Some(4)) // "2 and 4"
println(result1)
println(result2)
println(result3)
println(result4)