Can you pattern match on Python types?
I've seen simple examples:
import builtins
match x:
case builtins.str:
print("matched str")
case buildins.int:
print("matched int")
But I'd like to pattern match on a nested type, something like Annotated[Optional[Literal["a", "b", "c"]], "something here"]
- is this possible?
Pattern matching is fundamentally compiled down to a chained series of isinstance
and ==
calls, among others. This means that, if you can express Annotated[Optional[Literal["a", "b", "c"]], "something here"]
as a series of isinstance
, ==
, etc. calls, you can do pattern matching.
The problem with trying to do pattern matching on items from typing
is that the types of the objects typing.Annotated[...]
, typing.Optional[...]
, etc. are implementation details (they're subclasses of typing._GenericAlias
, and their instance variables and properties are not public), whereas pattern matching (specfically class patterns) is a style which ideally works with programming against a public API. If you don't care that you're accessing implementation details, then this could work:
import types
from typing import *
x = Annotated[Optional[Literal["a", "b", "c"]], "something here"]
AnnotatedAlias = type(Annotated[Any, Any])
UnionAlias = type(Union[Any, None])
LiteralAlias = type(Literal[None])
match x:
case AnnotatedAlias(
__args__=(
UnionAlias(__args__=(LiteralAlias(__args__=("a", "b", "c")), types.NoneType)),
)
):
print("x matched")