У меня есть функция Python, которая извлекает первый элемент произвольного числа *args:
def get_first(*args):
return tuple(a[0] for a in args)
Допустим, я вызываю эту функцию следующим образом:
b = (1, 2, 3)
c = ("a", "b", "c", "d")
x = get_first(b, c)
Я ожидаю типа Tuple[int, str]. Мне кажется невозможным добиться правильной типизации, чтобы точно выявить этот тип.
Мне не повезло с TypeVarTuplePEP 646 или с Paramspec PEP 612.






Подпись, которую вы ищете, связана с подписью zip; на самом деле, вы можете реализовать свою функцию как next(zip(*args)).
К сожалению, на данный момент нет хорошего способа ввести такую функцию. Для этого потребуются вариативные дженерики, которые в настоящее время не реализованы. Например, вы можете увидеть подпись типа zipздесь:
@overload
def __new__(cls, *, strict: bool = ...) -> zip[Any]: ...
@overload
def __new__(cls, iter1: Iterable[_T1], /, *, strict: bool = ...) -> zip[tuple[_T1]]: ...
@overload
def __new__(cls, iter1: Iterable[_T1], iter2: Iterable[_T2], /, *, strict: bool = ...) -> zip[tuple[_T1, _T2]]: ...
@overload
def __new__(
cls, iter1: Iterable[_T1], iter2: Iterable[_T2], iter3: Iterable[_T3], /, *, strict: bool = ...
) -> zip[tuple[_T1, _T2, _T3]]: ...
@overload
def __new__(
cls, iter1: Iterable[_T1], iter2: Iterable[_T2], iter3: Iterable[_T3], iter4: Iterable[_T4], /, *, strict: bool = ...
) -> zip[tuple[_T1, _T2, _T3, _T4]]: ...
@overload
def __new__(
cls,
iter1: Iterable[_T1],
iter2: Iterable[_T2],
iter3: Iterable[_T3],
iter4: Iterable[_T4],
iter5: Iterable[_T5],
/,
*,
strict: bool = ...,
) -> zip[tuple[_T1, _T2, _T3, _T4, _T5]]: ...
@overload
def __new__(
cls,
iter1: Iterable[Any],
iter2: Iterable[Any],
iter3: Iterable[Any],
iter4: Iterable[Any],
iter5: Iterable[Any],
iter6: Iterable[Any],
/,
*iterables: Iterable[Any],
strict: bool = ...,
) -> zip[tuple[Any, ...]]: ...
Этот тип проверяет точно только до шести аргументов, что на практике достаточно хорошо, но является довольно повторяющимся и довольно неуклюжим. К сожалению, это, вероятно, лучшее, что вы можете сделать на данный момент.
С грустью приму ваш замечательный ответ :)
Если вы используете
v1, v2 = (a[0] for a in args), а затемreturn (v1, v2), вы получите кортеж(1, 'a'), который вы ожидали.