10

How to annotate parameters of the variadic function?

Example:

def foo(*args):  # Each arg expected to be of type T
    ...

Are there any typing annotations for that?

kuza
  • 2,761
  • 3
  • 22
  • 56
  • Related question: in order to type hint a `Callable` type like this refer to [Python type hint for Callable with variable number of str/same type arguments? - Stack Overflow](https://stackoverflow.com/questions/57658879/python-type-hint-for-callable-with-variable-number-of-str-same-type-arguments) ■ also possible duplicate of [python - Type annotations for *args and **kwargs - Stack Overflow](https://stackoverflow.com/questions/37031928/type-annotations-for-args-and-kwargs) – user202729 Nov 20 '22 at 01:18

2 Answers2

5

If each argument has a TheType type - annotate it as specified in PEP-484:

def foo(*args: TheType):
    ...

Do not use: def foo(*args: Tuple[TheType]):, because specifying Tuple[TheType] means it's a single-element tuple - with one TheType element, which is not what variadic args are intended to serve.

  • Well, specifying `Tuple[TheType]` actually means that you expect tuples of type `TheType` as your variable arguments. _Per se_ `args` is a homogeneous tuple already and the asterisk simply expands it. This is why you only left to annotate _the type_. – kuza Sep 09 '20 at 15:41
  • 1
    @kuza That is incorrect. What you mean is `Tuple[TheType, ...]`. See [the docs](https://docs.python.org/3/library/typing.html#typing.Tuple). Plain `Tuple[TheType]` refers to a non-variadic tuple with one element of type `TheType`. – Lukas Juhrich Sep 10 '22 at 15:28
4

tl;dr

Basically args treated as a homogeneous tuple and kwds as a dictionary. You simply annotate a type being expected for each element value.

Explanation

Explanation arrives from quote of the PEP-484:

In the body of function foo, the type of variable args is deduced as Tuple[str, ...] and the type of variable kwds is Dict[str, int].

So there is no need to annotate args as whole homogeneous typed tuple but one can reduce Tuple[T, ...] to just type T.

Same true for the keyword arguments as they deduced as Dict[str, T]

About ellipsis in the tuple annotation

In python documentation there is no much information about the usage of the ... a.k.a Ellipsis but PEP-484 does mention various usages of the ellipsis in typing annotations like for omitting some type annotations or default values but most interestingly there is a quote saying:

Tuple, used by listing the element types, for example Tuple[int, int, str]. The empty tuple can be typed as Tuple[()]. Arbitrary-length homogeneous tuples can be expressed using one type and ellipsis, for example Tuple[int, ...]. (The ... here are part of the syntax, a literal ellipsis.)

So if you omit asterisk to force passing arguments as a single tuple you need keep full annotation:

def foo(args: Tuple[T, ...]):
    ...

About various types in a homogeneous tuple

Since homogeneous tuple means all of its elements must be of the same type then if you wish to allow several types just use a Union or even use a type alias for better readability:

MyArg = Union[int, str, bool]

def foo(*args: MyArg):
    ...
user202729
  • 3,358
  • 3
  • 25
  • 36
kuza
  • 2,761
  • 3
  • 22
  • 56
  • 2
    Are you sure that's the right way? According to [the pep](https://www.python.org/dev/peps/pep-0484/#arbitrary-argument-lists-and-default-argument-values) varargs aren't annotated as `Tuple`, but rather like `def foo(*args: str):` (and not `Tuple[str]`). So, wouldn't your annotation mean that your function accepts a variable number of homogeneous tuples? – Aran-Fey Feb 21 '18 at 15:48
  • Hm… I probably missed that because I was looking for ellipsis as I remembered there was a way involving it. Also, I find no problems with annotating it as `Tuple` and within a function, it does pass test `isinstance(args, tuple)`. Please, note without `*` asterisk. I believe `*args: T` is a shorthand for `*args: Tuple[T, ...]` so I observe no troubles with that. – kuza Feb 21 '18 at 16:07
  • 1
    Well, @Aran-Fey PyCharm and IDEA of today do not understand full syntax correctly and recognize correctly the shorter version as you mentioned. – kuza Feb 21 '18 at 16:36
  • @kuza you accepted your answer to your own question, but the problem is that it's incorrect. – Mikaelblomkvistsson Sep 07 '20 at 14:25
  • Well, I did correct myself after an update, quoting PEP 484. Perhaps it was tl;dr for you? I will try shrinking my answer to the point. – kuza Sep 09 '20 at 09:28