More consistent typing annotations for tuple

I know it’s too late to change it, but as though exercise, I’ve been thinking if one day Python was recreated from scratch, could typing annotation for tuple be improved:

Currently there’s a big inconsistency between tuple[str] vs list[str]. It’s a very common error (from a quick search on github, it’s easy to find hundreds of examples).

Couldn’t have it been better to have tuple[X] be consistent with list[X] and instead introduce a new special syntax for tuple[X, ...]:


x: tuple[T]
x: tuple[int, float]
x: tuple[int, ...]


x: (T,)
x: (int, float)
x: (int, ...)  # Or tuple[int]

This would of course create the issue of knowing when a (int,) should be a tuple vs a types.GenericAlias, but maybe typing.get_type_hints() could normalize tuple to some special class, like:

def zip(x: _T1, y: _T2) -> (_T1, _T2):

typing.get_type_hints(zip) == {
    'return': TupleArgs[_T1, _T2]

Another edge case is that there’s no distinction between x[int, int] and x[(int, int)], but maybe that’s another thing to fix :sweat_smile:

It’s not really serious, and I’m sure there’s lot of edge cases I didn’t concidered, but it’s interesting to think about.

1 Like

I had the same thought yesterday: Writing `tuple[T, U, V]` as `(T, U, V)`

Possibly, depending on who’s judging the improvement. But it should be noted that Python’s development started all the way back in 1989 (older than Java!); the first version with an annotations feature (not specifically intended for typing!) was 3.0, released in 2008; and the first version with a typing standard library module was 3.5, released in 2015. An alternate-universe Python designed for typing annotations might well enforce them in compilation; it would be a different language for sure.

This is by design. While the actual semantic effect is that tuples are immutable while tuples are mutable, there is an ages-long precedent that, stylistically, tuples are intended to be used for heterogeneous collections of values where there’s a type known in advance for each element (like a struct or record in languages that make those concepts first-class), whereas lists are intended to be used for homogeneous collections of values that share a type but whose count may vary at runtime (like a typed array or vector in languages that make those concepts first-class).