@@ -151,15 +151,16 @@ In order to support the above use cases, we introduce
151151but for a *tuple * of types.
152152
153153In addition, we introduce a new use for the star operator: to 'unpack'
154- ``TypeVarTuple `` instances and tuple types. Unpacking a
155- `` TypeVarTuple `` or tuple type is the typing equivalent of unpacking a
156- variable or a tuple of values.
154+ ``TypeVarTuple `` instances and tuple types such as `` Tuple[int,
155+ str] ``. Unpacking a `` TypeVarTuple `` or tuple type is the typing
156+ equivalent of unpacking a variable or a tuple of values.
157157
158158Type Variable Tuples
159159--------------------
160160
161- In the same way that a normal type variable is a stand-in for a single type,
162- a type variable *tuple * is a stand-in for a *tuple * type.
161+ In the same way that a normal type variable is a stand-in for a single
162+ type such as ``int ``, a type variable *tuple * is a stand-in for a *tuple * type such as
163+ ``Tuple[int, str] ``.
163164
164165Type variable tuples are created with:
165166
@@ -169,8 +170,8 @@ Type variable tuples are created with:
169170
170171 Ts = TypeVarTuple('Ts')
171172
172- Using a Type Variable Tuple in Generic Classes
173- ''''''''''''''''''''''''''''''''''''''''''''''
173+ Using Type Variable Tuples in Generic Classes
174+ '''''''''''''''''''''''''''''''''''''''''''''
174175
175176Type variable tuples behave like a number of individual type variables packed in a
176177``Tuple ``. To understand this, consider the following example:
@@ -204,8 +205,8 @@ and so on:
204205 y: Array[Batch, Height, Width] = Array()
205206 z: Array[Time, Batch, Height, Width] = Array()
206207
207- Using a Type Variable Tuple in Functions
208- ''''''''''''''''''''''''''''''''''''''''
208+ Using Type Variable Tuples in Functions
209+ '''''''''''''''''''''''''''''''''''''''
209210
210211Type variable tuples can be used anywhere a normal ``TypeVar `` can.
211212This includes class definitions, as shown above, as well as function
@@ -315,12 +316,10 @@ As of this PEP, only a single type variable tuple may appear in a type parameter
315316
316317 class Array(Generic[*Ts1, *Ts2]): ... # Error
317318
318- Only one unpacking may appear in a tuple:
319+ The reason is that multiple type variable tuples make it ambiguous
320+ which parameters get bound to which type variable tuple: ::
319321
320- ::
321-
322- x: Tuple[int, *Ts, str, *Ts2] # Error
323- y: Tuple[int, *Tuple[int, ...], str, *Tuple[str, ...]] # Error
322+ x: Array[int, str, bool] # Ts1 = ???, Ts2 = ???
324323
325324Type Concatenation
326325------------------
@@ -361,71 +360,36 @@ Normal ``TypeVar`` instances can also be prefixed and/or suffixed:
361360 z = prefix_tuple(x=0, y=(True, 'a'))
362361 # Inferred type of z is Tuple[int, bool, str]
363362
364- Unpacking a Tuple Type
365- ----------------------
363+ Unpacking Tuple Types
364+ ---------------------
366365
367- We mentioned that a ``TypeVarTuple `` simply stands for a tuple of
368- types. Thus, we can cleanly replace any use of a ``TypeVarTuple `` in a
369- function signature with a tuple type.
366+ We mentioned that a ``TypeVarTuple `` stands for a tuple of types.
367+ Since we can unpack an ``TypeVarTuple ``, for consistency, we also
368+ allow unpacking a tuple type. As we shall see, this also enables a
369+ number of interesting features.
370370
371- Unpacking a Concrete Tuple Type
372- '''''''''''''''''''''''''''''''
371+
372+ Unpacking Concrete Tuple Types
373+ ''''''''''''''''''''''''''''''
373374
374375Unpacking a concrete tuple type is analogous to unpacking a tuple of
375376values at runtime. ``Tuple[int, *Tuple[bool, bool], str] `` is
376- equivalent to ``Tuple[int, bool, bool, str] ``. While this is unlikely
377- to be useful by itself, we mention it to cleanly specify how we unpack
378- a ``TypeVarTuple `` that is substituted by a concrete tuple type:
379-
380- ::
381-
382- def strip_and_add_float(x: Tuple[int, *Ts, str]) -> Tuple[float, *Ts, float]: ...
383-
384- When ``strip_and_add_float `` is called with a value that has a concrete
385- tuple type, say, ``Tuple[int, bool, bool, str] ``, ``Ts `` is bound to
386- the concrete tuple ``Tuple[bool, bool] ``.
387-
388- ::
389-
390- x: Tuple[int, bool, bool, str] = (1, True, False, "hello")
391-
392- y = strip_and_add_float(x)
393- # Inferred type of y: Tuple[float, bool, bool, float]
377+ equivalent to ``Tuple[int, bool, bool, str] ``.
394378
395- The inferred type is ``Tuple[float, bool, bool, float] `` because
396- unpacking ``Tuple[bool, bool] `` in the return type ``Tuple[float, *Ts,
397- float] `` gives back ``Tuple[float, bool, bool, float] ``.
398-
399- Unpacking an Unbounded Tuple Type
400- '''''''''''''''''''''''''''''''''
379+ Unpacking Unbounded Tuple Types
380+ '''''''''''''''''''''''''''''''
401381
402382Unpacking an unbounded tuple preserves the unbounded tuple as it is.
403- ``Tuple[int, *Tuple[str, ...], str] `` signifies a tuple
404- type where the first element is guaranteed to be of type ``int ``, the
405- last element is guaranteed to be of type ``str ``, and there may be
406- zero or more elements of type ``str `` in between. Note that
407- ``Tuple[*Tuple[int, ...]] `` is equivalent to ``Tuple[int, ...] ``.
408-
409- Consider the following functions:
410-
411- ::
412-
413- def add_first_last(x: Tuple[*Ts]) -> Tuple[int, *Ts, str]: ...
414-
415- When ``add_first_last `` is called with a value that has an *unbounded *
416- tuple type, say, ``Tuple[str, ...] ``, ``Ts `` is bound to the concrete
417- tuple ``Tuple[str, ...] `` and substituted in the return type.
418-
419- ::
420-
421- x: Tuple[str, ...]
422-
423- y = add_first_last(x)
424- # Inferred type of y: Tuple[int, *Tuple[str, ...], str]
425-
426-
427- Unpacking unbounded tuples is useful in function signatures where we
428- don't care about the exact elements and do not want to define an
383+ That is, ``*Tuple[int, ...] `` remains ``*Tuple[int, ...] ``; there's no
384+ simpler form. This enables us to specify types such as ``Tuple[int,
385+ *Tuple[str, ...], str] `` - a tuple type where the first element is
386+ guaranteed to be of type ``int ``, the last element is guaranteed to be
387+ of type ``str ``, and the elements in the middle are zero or more
388+ elements of type ``str ``. Note that ``Tuple[*Tuple[int, ...]] `` is
389+ equivalent to ``Tuple[int, ...] ``.
390+
391+ Unpacking unbounded tuples is also useful in function signatures where
392+ we don't care about the exact elements and don't want to define an
429393unnecessary ``TypeVarTuple ``:
430394
431395::
@@ -444,25 +408,26 @@ unnecessary ``TypeVarTuple``:
444408 process_batch_channels(z) # Error: Expected Channels.
445409
446410
447- We can also pass a ``Tuple[int, ...] `` wherever a ``Tuple[ *Ts] `` is
411+ We can also pass a ``* Tuple[int, ...] `` wherever a ``*Ts `` is
448412expected. This is useful when we have particularly dynamic code and
449- cannot infer the precise number of dimensions or the precise types for
413+ cannot state the precise number of dimensions or the precise types for
450414each of the dimensions. In those cases, we can smoothly fall back to
451415an unbounded tuple:
452416
453417::
454418
419+ y: Array[*Tuple[Any, ...]] = read_from_file()
420+
455421 def expect_variadic_array(
456422 x: Array[Batch, *Shape]
457423 ) -> None: ...
458424
425+ expect_variadic_array(y) # OK
426+
459427 def expect_precise_array(
460428 x: Array[Batch, Height, Width, Channels]
461429 ) -> None: ...
462430
463- y: Array[*Tuple[Any, ...]] = read_from_file()
464-
465- expect_variadic_array(y) # OK
466431 expect_precise_array(y) # OK
467432
468433``Array[*Tuple[Any, ...]] `` stands for an array with an arbitrary
@@ -473,10 +438,23 @@ is bound to ``Tuple[Any, ...]``. In the call to
473438``Width ``, and ``Channels `` are all bound to ``Any ``.
474439
475440This allows users to handle dynamic code gracefully while still
476- explicitly marking the code as unsafe (by using ``*Tuple[Any, ...] ``).
477- Otherwise, users would face noisy errors from the type checker every
478- time they tried to use the variable ``y ``, which would hinder them
479- when migrating a legacy code base to use ``TypeVarTuple ``.
441+ explicitly marking the code as unsafe (by using ``y: Array[*Tuple[Any,
442+ ...]] ``). Otherwise, users would face noisy errors from the type
443+ checker every time they tried to use the variable ``y ``, which would
444+ hinder them when migrating a legacy code base to use ``TypeVarTuple ``.
445+
446+ Multiple Unpackings in a Tuple: Not Allowed
447+ '''''''''''''''''''''''''''''''''''''''''''
448+
449+ As with `TypeVarTuples <Multiple Type Variable Tuples: Not
450+ Allowed_> `_, only one unpacking may appear in a tuple:
451+
452+
453+ ::
454+
455+ x: Tuple[int, *Ts, str, *Ts2] # Error
456+ y: Tuple[int, *Tuple[int, ...], str, *Tuple[str, ...]] # Error
457+
480458
481459``*args `` as a Type Variable Tuple
482460----------------------------------
@@ -508,18 +486,19 @@ or suffixes of the variadic argument list. For example:
508486::
509487
510488 # os.execle takes arguments 'path, arg0, arg1, ..., env'
511- def execle(path: str, *args: *Tuple[*Ts, Mapping[str, str] ]) -> None: ...
489+ def execle(path: str, *args: *Tuple[*Ts, Env ]) -> None: ...
512490
513- Note this this is different to
491+ Note that this is different to
514492
515493::
516494
517- def execle(path: str, *args: *Ts, env: Mapping[str, str] ) -> None: ...
495+ def execle(path: str, *args: *Ts, env: Env ) -> None: ...
518496
519497as this would make ``env `` a keyword-only argument.
520498
521- Unpacking an unbounded tuple is equivalent to the PEP 484 behavior of
522- ``*args: int ``, which accepts zero or more values of type ``int ``:
499+ Using an unpacked unbounded tuple is equivalent to the PEP 484
500+ behavior [#pep-484-args ]_ of ``*args: int ``, which accepts zero or
501+ more values of type ``int ``:
523502
524503::
525504
@@ -587,10 +566,10 @@ Type variable tuples can also be used in the arguments section of a
587566 def __init__(
588567 self,
589568 target: Callable[[*Ts], None],
590- args: Tuple[*Ts]
591- ): ...
569+ args: Tuple[*Ts],
570+ ) -> None : ...
592571
593- def func(arg1: int, arg2: str): ...
572+ def func(arg1: int, arg2: str) -> None : ...
594573
595574 Process(target=func, args=(0, 'foo')) # Valid
596575 Process(target=func, args=('foo', 0)) # Error
@@ -621,7 +600,7 @@ the function:
621600 def foo(*args: *Tuple[int, *Ts, T]) -> Tuple[T, *Ts]: ...
622601
623602Behaviour when Type Parameters are not Specified
624- ''''''''''''''''''''''''''''''''''''''''''''''''
603+ ------------------------------------------------
625604
626605When a generic class parameterised by a type variable tuple is used without
627606any type parameters, it behaves as if the type variable tuple was
@@ -654,7 +633,7 @@ This also works in the opposite direction:
654633
655634 takes_specific_array(z)
656635
657- (For details, see the section on `Unpacking an Unbounded Tuple Type `_.)
636+ (For details, see the section on `Unpacking Unbounded Tuple Types `_.)
658637
659638This way, even if libraries are updated to use types like ``Array[Height, Width] ``,
660639users of those libraries won't be forced to also apply type annotations to
@@ -729,7 +708,7 @@ Normal ``TypeVar`` instances can also be used in such aliases:
729708 Foo[str, int]
730709 # T bound to float, Ts to Tuple[()]
731710 Foo[float]
732- # T bound to Any, Ts to an arbitrary number of Any
711+ # T bound to Any, Ts to an Tuple[ Any, ...]
733712 Foo
734713
735714Overloads for Accessing Individual Types
@@ -810,8 +789,8 @@ otherwise imply. Also, we may later wish to support arguments that should not be
810789
811790We therefore settled on ``TypeVarTuple ``.
812791
813- Unspecified Type Parameters: Tuples vs TypeVarTuples
814- ----------------------------------------------------
792+ Unspecified Type Parameters: Tuple vs TypeVarTuple
793+ --------------------------------------------------
815794
816795In order to support gradual typing, this PEP states that *both *
817796of the following examples should type-check correctly:
@@ -1470,6 +1449,8 @@ References
14701449
14711450 .. [#dan-endorsement ] https://mail.python.org/archives/list/python-dev@python.org/message/HTCARTYYCHETAMHB6OVRNR5EW5T2CP4J/
14721451
1452+ .. [#pep-484-args ] https://www.python.org/dev/peps/pep-0484/#arbitrary-argument-lists-and-default-argument-values
1453+
14731454 Copyright
14741455=========
14751456
0 commit comments