Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to annotate function that takes a tuple of variable length? (variadic tuple type annotation)

I have a function that takes a tuple of different lengths as an argument:

from typing import Tuple   def process_tuple(t: Tuple[str]):     # Do nasty tuple stuff  process_tuple(("a",)) process_tuple(("a", "b")) process_tuple(("a", "b", "c"))  

When I annotate function like mentioned above, I get these error messages

fool.py:9: error: Argument 1 to "process_tuple" has incompatible type "Tuple[str, str]"; expected "Tuple[str]" fool.py:10: error: Argument 1 to "process_tuple" has incompatible type "Tuple[str, str, str]"; expected "Tuple[str]" 

process_tuple really works with tuples and I use them as immutable lists of variable length. I haven't found any consensus on this topic on the internet, so I wonder how should I annotate this kind of input.

like image 442
Montreal Avatar asked Feb 18 '19 12:02

Montreal


2 Answers

We can annotate variable-length homogeneous tuples using the ... literal (aka Ellipsis) like this:

def process_tuple(t: Tuple[str, ...]):     ... 

After that, the errors should go away.

From the docs:

To specify a variable-length tuple of homogeneous type, use literal ellipsis, e.g. Tuple[int, ...]. A plain Tuple is equivalent to Tuple[Any, ...], and in turn to tuple.

like image 178
Azat Ibrakov Avatar answered Sep 22 '22 12:09

Azat Ibrakov


In addition to the Ellipsis answer as posted by Azat you could make it more explicit by using @typing.overload or typing.Union

from typing import Tuple   @overload def process_tuple(t: Tuple[str]):     # Do nasty tuple stuff  @overload def process_tuple(t: Tuple[str, str]):     ... 

Or with the Union:

from typing import Tuple, Union   def process_tuple(t: Union[Tuple[str], Tuple[str, str], Tuple[str, str, str]]):     # Do nasty tuple stuff 
like image 20
Wolph Avatar answered Sep 23 '22 12:09

Wolph