Например (это не совсем тот код, который я использую, это минимальный иллюстративный пример). ), предположим, я определяю пару литералов:
Код: Выделить всё
_S = Literal["str"]
_I = Literal["int"]
Код: Выделить всё
@overload
def get_func(name: _K) -> Callable[[int], str]:
...
@overload
def get_func(name: _L) -> Callable[[str], str]:
...
def get_func(name: _K | _L) -> Callable[[int], str] | Callable[[str], str]:
match name:
case "int":
return from_int
case "str":
return from_str
case _:
# Handle the possible runtime error
raise ValueError("OMG error or something.")
def process_args(args: tuple[_K | _L, ...]) -> tuple[Callable[[int], str] | Callable[[str], str], ...]:
base: tuple[Callable[[int], str] | Callable[[str], str], ...] = tuple()
for arg in args:
base += (get_func(arg), )
return base
funcs = process_args(("str", "str", "int"))
reveal_type(funcs)
Код: Выделить всё
Revealed type is "builtins.tuple[Union[def (builtins.int) -> builtins.str, def (builtins.str) -> builtins.str], ...]"
Я мог бы в некоторой степени обойти это, сделав больше такие перегрузки:
Код: Выделить всё
@overload
def get_func_tuple(args: tuple[_K, ...]) -> tuple[Callable[[int], str], ...]:
...
@overload
def get_func_tuple(args: tuple[_L, ...]) -> tuple[Callable[[str], str], ...]:
...
@overload
def get_func_tuple(args: tuple[_L, _K]) -> tuple[Callable[[str], str], Callable[[int], str]]:
...
@overload
def get_func_tuple(args: tuple[_K, _L]) -> tuple[Callable[[int], str], Callable[[str], str]]:
...
@overload
def get_func_tuple(args: tuple[_K, _L, _K]) -> tuple[Callable[[int], str], Callable[[str], str], Callable[[int], str]]:
...
@overload
def get_func_tuple(args: tuple[_L, _K, _L]) -> tuple[Callable[[str], str], Callable[[int], str], Callable[[str], str]]:
...
@overload
def get_func_tuple(args: tuple[_K, _L, _L, _K]) -> tuple[Callable[[str], str], Callable[[int], str], Callable[[int], str], Callable[[str], str]]:
...
@overload
def get_func_tuple(args: tuple[_L, _K, _K, _L]) -> tuple[Callable[[int], str], Callable[[str], str], Callable[[str], str], Callable[[int], str]]:
...
def get_func_tuple(args: tuple[_K | _L, ...]) -> tuple[Callable[[int], str] | Callable[[str], str], ...]:
return tuple((get_func(x) for x in args))
func2 = get_func_tuple(("int", "str", "str", "int"))
reveal_type(func2)
Код: Выделить всё
Revealed type is "tuple[def (builtins.int) -> builtins.str, def (builtins.str) -> builtins.str, def (builtins.str) -> builtins.str, def (builtins.int) -> builtins.str]"
т.е.
Код: Выделить всё
A --> X
B --> Z
(A, B) ==> (X, Z)
(A, ) ==> (X, )
(A, A, A) ==> (X, X, X)
(A, B, B, A, B) ==> (X, Z, Z, X, Z)
Подробнее здесь: https://stackoverflow.com/questions/777 ... iterable-w