Как сопоставить подсказки типа Python с порядком значений в неоднородной итерации без ручной записи каждой перестановки Python

Программы на Python
Anonymous
Как сопоставить подсказки типа Python с порядком значений в неоднородной итерации без ручной записи каждой перестановки

Сообщение Anonymous »

Мне нужно сопоставить порядок аргументов с различными перестановками набора переданных аргументов.
Например (это не совсем тот код, который я использую, это минимальный иллюстративный пример). ), предположим, я определяю пару литералов:

Код: Выделить всё

_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], ...]"
Потому что, конечно, это то, что есть. Мне бы хотелось найти способ изменять тип возвращаемого значения (так же, как перегрузка get_func ).
Я мог бы в некоторой степени обойти это, сделав больше такие перегрузки:

Код: Выделить всё


@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)
Здесь показан тип 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

Вернуться в «Python»