Choose a tuple annotation by deciding whether its length is fixed or variable, and whether each position has its own type. For example, tuple[int, str] describes exactly two positions, while tuple[int, ...] describes any number of integers. These annotations help static type checkers catch mismatches; they do not validate values at runtime.
Choose the tuple annotation that matches its shape
In modern Python, write tuple annotations with the built-in tuple type and square brackets. The number and form of the type arguments communicate the contract to readers and static type checkers.
| Annotation | Meaning | Example |
|---|---|---|
tuple[int, str] |
Exactly two elements: an int first and a str second. |
(42, "ready") |
tuple[int] |
Exactly one element, of type int. It does not mean an arbitrary-length tuple of integers. |
(8,) |
tuple[int, ...] |
Any number of elements, all of type int. |
(8, 13, 21) |
tuple[()] |
An empty tuple. | () |
tuple |
Equivalent to tuple[Any, ...]: arbitrary length and element types. |
(8, "ready", True) |
The Python 3.13 typing documentation describes tuple[T, ...] as a tuple of any length whose elements all have type T.
Annotate fixed-position tuples
Use one type argument for each position when the tuple has a known length and the positions may differ in type. A coordinate, for instance, can have two floating-point values; a compact record can combine an integer, string, and Boolean:
#1 Best Overall
point: tuple[float, float] = (2.5, 7.0)
record: tuple[int, str, bool] = (42, "ready", True)
Order matters: tuple[int, str] and tuple[str, int] express different contracts. A type checker can flag an assignment that has the wrong number of items or types in those positions.
Annotate variable-length tuples with one element type
When a tuple may contain any number of values but they should all share a type, put that type before an ellipsis:
Rank #2
scores: tuple[int, ...] = (8, 13, 21)
no_scores: tuple[int, ...] = ()
The ellipsis means the tuple length is not fixed. This differs from tuple[int], which allows exactly one integer. Use tuple[()] instead when the contract specifically requires an empty tuple.
Use syntax supported by the project’s Python version
The built-in tuple[...] annotation form is supported starting with Python 3.9. If a project must run on an older interpreter, the older spelling from typing is commonly used:
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchfrom typing import Tuple
point: Tuple[float, float] = (2.5, 7.0)
Choose syntax based on the minimum Python version the project supports, not only the version installed on one developer’s machine. Python 3.10’s typing documentation covers annotations and the role of typing tools.
Use variadic generics only for type-preserving APIs
Most tuples need either a fixed positional annotation or a homogeneous variable-length annotation. A generic API that accepts and returns a tuple while preserving an arbitrary sequence of distinct positional types may need a variadic generic, such as TypeVarTuple and unpacking:
def identity[*Ts](value: tuple[*Ts]) -> tuple[*Ts]:
return value
For older forms, unpacking can be expressed with Unpack[Ts]. This is advanced syntax; check both interpreter and type-checker support before adopting it. See the Python 3.13 and 3.14 typing documentation.
Remember that annotations do not validate runtime data
Python does not enforce function or variable annotations while a program runs. As the Python 3.10 typing documentation puts it, “The Python runtime does not enforce function and variable type annotations.” An annotation can inform a type checker and document an interface, but it cannot guarantee that a value read from JSON, a file, a network request, or another untyped source actually matches that interface.
Recommended Free Tools
Best Value
If external input must be trusted, validate it separately at the boundary where it enters the application. Keep that runtime check distinct from the annotation: the annotation describes the expected shape, while validation checks the actual value. Tuple annotations also do not change the ordinary behavior of tuples or make the objects they contain immutable.
Quick Recap
A quick decision guide
- Known length and potentially different types by position: use
tuple[T1, T2, ...]. - Any length, one shared element type: use
tuple[T, ...]. - Exactly one item: use
tuple[T]. - Only the empty tuple: use
tuple[()]. - Arbitrary values with no more precise contract: bare
tupleis equivalent totuple[Any, ...]. - Preserve a generic sequence of distinct positional types: consider variadic generics if the supported Python and type-checker versions allow them.
- Untrusted values: add runtime validation; an annotation alone is not a check.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




