You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
At a high level, everything between the * and the TypeVarTuple it expands would be applied per type in the tuple before it's unpacked.
There are some decisions to be made about how the expansion is done if there are multiple TypeVarTuples in the expand expression, but I think it can be supported and I think the intuitive thing would be to zip up all the TypeVarTuples. For example, tuple[*tuple[Ts, Us]] with Ts = (int, str) and Us = (float, bytes) would be tuple[tuple[int, float], tuple[str, bytes]], with the implementation enforcing equal-length TypeVarTuples.
If there's a workaround for this using the existing logic, let me know. My current use case involves keeping a reference to the runtime types, so *type[Ts] is what I'm looking for at the moment.
@llchan Yes, we plan to add a follow-up PEP to PEP 646 with support for such mapping (hopefully, later this year). We cut it from the original PEP because the PEP was already pretty complicated.
Reacted by Lawrence Chan, Hash, Markus, applepi-icpc and Bar Harel
Reacted by Ellis Breen, Anthony Platanios, Riccardo Bergamaschi and racinette
Great to hear. If/when there's an official tracking issue or link to a discussion it would be helpful to include a reference here (and feel free to close this if it's superceded).
As an aside would there be a way to map a tuple[T1, T2, T3] -> tuple[U1, U2, U3], in effect just preserving the shape but not the types themselves. Use case (pretending bounds exist)
defbuy_items[*AppShopItemTs: AppShopItem](self, *items: *AppShopItemTs) -> ...: # not sure what the return should look like"""Buy the ``items`` from the in-app store. Returns: The items in the user's inventory, bought from the store"""
Not sure if this is exactly the same structure as others in this thread, but here's possibly another use-case of this sort of thing: I have a function my_func accepts that accepts a list of callables some_callables that output different types, and the my_func's output will match exactly one of those types:
defmy_func[*Ts](
some_callables: list[
callable[
[],
OneOf[*Ts] # or however one would express this - maybe "Map", or even "T in Ts" ?
]]
) ->Union[*Ts]:
returnrandom.choice(some_callables)()
deff() ->int:
return1defg() ->str:
return""x: int|str=my_func([f, g]) # the type hint here should be inferrable
I think that list[callable[..., Union[*Ts]]] would be the wrong type for the outputs themselves (they each output one of the types, not a Union), thus the fictional OneOf (or Map, or whatever).
defprod_fn[*Us, *Vs](*funcs: ???) ->Callable[[*Us], tuple[*Vs]]:
r"""Cartesian Product of Functions. It is assumed every function takes a single positional argument. """def__prod_fn(*args: *Us) ->tuple[*Vs]:
"""Argument is a tuple with the input for each function."""returntuple(f(arg) forf, arginzip(funcs, args))
return__prod_fn
Here, funcs is the variable length tuple[Callable[[U₁], V₁]], Callable[[U₂], V₂]], ..., Callable[[Uₙ], Vₙ]]]. Possibly syntax:
*funcs: *Map[(Us, Vs), Callable[[Us], Vs]]] (suggested by David in this discussion)
*funcs: *tuple[Callable[[U], V]] for U, V in zip(Us, Vs)] (comprehension syntax suggested by @zen-xu)
Mmh, I find that notation a bit confusing. The left U refers to the TypeVarTuple and the right U refers to the item in the U tuple?
Hm, I guess notationally something like: *funcs: *Map[Func, Us, Vs], with the type alias type Func[U,V] = Callable[[U], V] would be better, with a typing.Map that behaves like builtins.map, but for generic types.
Notably, such a construct is also required to even type hint builtins.map properly. If we look at the current stubs in typeshed, it's only a Generic Iterator[S] with manual @overloads for up to 6 iterables. It probably should be type hinted be something along the lines of:
classmap[F: Callable[[*Ts], S], *Ts]:
@overloaddef__new__(cls, func: F, /) ->Never: ... # need at least 1 iterable.@overloaddef__new__(cls, func: F, /, *iterables: *Map[Iterable, Ts]) ->Self: ...
def__iter__(self) ->Self: ...
def__next__(self) ->S: ...
Are there any plans on adding this feature? It was mentioned that they were planning to release a follow-up PEP later in 2022, but it has been two years. Has this been abandoned or forgotten?
Keep in mind that it took nearly two years for mypy to implement support for the existing TypeVarTuple functionality defined in PEP 646. Pyre and pytype still don't support it.
If you're interested in proposing extensions to TypeVarTuple and would like to champion a new PEP, a good starting point is to create a discussion in the Python typing forum here.
Alright, thanks for the quick response! I am interested in championing a new PEP for this, although am unsure if I have enough experience to do so. I will have to look into it.
Activity
pradeep90 commentedon Jun 27, 2022
@llchan Yes, we plan to add a follow-up PEP to PEP 646 with support for such mapping (hopefully, later this year). We cut it from the original PEP because the PEP was already pretty complicated.
llchan commentedon Jun 27, 2022
Great to hear. If/when there's an official tracking issue or link to a discussion it would be helpful to include a reference here (and feel free to close this if it's superceded).
uriyyo commentedon Dec 13, 2022
Hi @pradeep90,
It would be great if it also will be possible to "unwrap"
TypeVarTuple.For instance:
I would love to hear your opinion regarding this feature.
maflAT commentedon May 12, 2023
I ran into this use case today, trying to annotate Qt for Python's
Slot()decorator.It requires the types of the decorated methods' arguments as parameters.
https://stackoverflow.com/questions/76234660/type-hinting-instances-vs-types-with-variadic-generics
Has there been any development regarding this topic since it was opened?
Add a new async iterable select() function
Add a new async iterable select() function
yakMM commentedon Aug 20, 2023
This would be great, and I'm interested for a workaround for
*type[Ts]if any.Kroppeb commentedon Sep 13, 2023
It would also be nice to be able to this to TypedDicts and ParamSpecs (and ParamSpecArgs and ParamSpecKwargs)
Gobot1234 commentedon Sep 16, 2023
As an aside would there be a way to map a
tuple[T1, T2, T3]->tuple[U1, U2, U3], in effect just preserving the shape but not the types themselves. Use case (pretending bounds exist)is a cute idea and I think I have seen generator expressions as an idea for a shorthand to Map come up a few times
insilications commentedon Oct 7, 2023
We definitely need this kind of typing.Map-like feature
randolf-scholz commentedon Oct 21, 2023
Probably duplicate of #1273, specialized to
TypeVarTuple.This would indeed be very nice, another use-case: column-oriented tables like
pyarrow.Tableorpandas.DataFrame.EDIT: Updated using the proposed comprehension syntax by @zen-xu for easier readability
phdowling commentedon Nov 19, 2023
Not sure if this is exactly the same structure as others in this thread, but here's possibly another use-case of this sort of thing: I have a function
my_funcaccepts that accepts a list of callablessome_callablesthat output different types, and themy_func's output will match exactly one of those types:I think that
list[callable[..., Union[*Ts]]]would be the wrong type for the outputs themselves (they each output one of the types, not a Union), thus the fictional OneOf (or Map, or whatever).randolf-scholz commentedon Dec 20, 2023
Here is another related example:
Here,
funcsis the variable lengthtuple[Callable[[U₁], V₁]], Callable[[U₂], V₂]], ..., Callable[[Uₙ], Vₙ]]]. Possibly syntax:*funcs: *Map[(Us, Vs), Callable[[Us], Vs]]](suggested by David in this discussion)*funcs: *tuple[Callable[[U], V]] for U, V in zip(Us, Vs)](comprehension syntax suggested by @zen-xu)Kroppeb commentedon Jan 21, 2024
Mmh, I find that notation a bit confusing. The left
Urefers to theTypeVarTupleand the rightUrefers to the item in theUtuple?randolf-scholz commentedon Jan 21, 2024
Hm, I guess notationally something like:
*funcs: *Map[Func, Us, Vs], with the type aliastype Func[U,V] = Callable[[U], V]would be better, with atyping.Mapthat behaves likebuiltins.map, but for generic types.Notably, such a construct is also required to even type hint
builtins.mapproperly. If we look at the current stubs intypeshed, it's only a GenericIterator[S]with manual@overloadsfor up to 6 iterables. It probably should be type hinted be something along the lines of:tanrbobanr commentedon Mar 27, 2024
Are there any plans on adding this feature? It was mentioned that they were planning to release a follow-up PEP later in 2022, but it has been two years. Has this been abandoned or forgotten?
erictraut commentedon Mar 27, 2024
There are no concrete plans currently.
Keep in mind that it took nearly two years for mypy to implement support for the existing
TypeVarTuplefunctionality defined in PEP 646. Pyre and pytype still don't support it.If you're interested in proposing extensions to
TypeVarTupleand would like to champion a new PEP, a good starting point is to create a discussion in the Python typing forum here.tanrbobanr commentedon Mar 27, 2024
Alright, thanks for the quick response! I am interested in championing a new PEP for this, although am unsure if I have enough experience to do so. I will have to look into it.
zen-xu commentedon May 23, 2024
If
TypeVarTuplesupports list comprehensionIn addition, it also supports for type guards.
ahmed-mahran commentedon Aug 8, 2024
For people interested in
*type[Ts]workarounds, you may check https://github.com/ahmed-mahran/funpy/blob/main/typeargs.py.There is also a PoC implementation of variadic generics transformations at https://github.com/ahmed-mahran/funpy/blob/main/mapped.py.
jorenham commentedon Aug 8, 2024
@ahmed-mahran It looks like your also trying to implement higher-kinded typing (HKT) with your examples, see #548 .
This made me realize that this issue is actually about variadic HKT.
bharel commentedon Sep 5, 2024
SO questions requesting that feature
https://stackoverflow.com/q/73200382/1658617
https://stackoverflow.com/q/78954770/1658617
fzimmermann89 commentedon Sep 25, 2024
Additional SO question:
https://stackoverflow.com/questions/78013162/typehint-function-args-tupleargs-with-constraint-on-the-args
vdozier-work commentedon Jan 21, 2025
This syntax has been suggested already:
We could use a similar syntax to describe typevars which may be one of the types in
*Vs(essentially a constraint):This would be as opposed to
V: Union[*Vs], I think