How to annotate types of multiple return values?
You are always returning one object; using return one, two
simply returns a tuple.
So yes, -> Tuple[bool, str]
is entirely correct.
Only the Tuple
type lets you specify a fixed number of elements, each with a distinct type. You really should be returning a tuple, always, if your function produces a fixed number of return values, especially when those values are specific, distinct types.
Other sequence types are expected to have one type specification for a variable number of elements, so typing.Sequence
is not suitable here. Also see What's the difference between lists and tuples?
Tuples are heterogeneous data structures (i.e., their entries have different meanings), while lists are homogeneous sequences. Tuples have structure, lists have order.
Python's type hint system adheres to that philosophy, there is currently no syntax to specify an iterable of fixed length and containing specific types at specific positions.
If you must specify that any iterable will do, then the best you can do is:
-> Iterable[Union[bool, str]]
at which point the caller can expect booleans and strings in any order, and of unknown length (anywhere between 0 and infinity).
Last but not least, as of Python 3.9, you can use
-> tuple[bool, str]
instead of -> Tuple[bool, str]
; support for type hinting notation has been added to most standard-library container types (see PEP 585 for the complete list). In fact, you can use this as of Python 3.7 too provided you use the from __future__ import annotations
compiler switch for your modules and a type checker that supports the syntax.
Related videos on Youtube
![Richard Hansen](https://i.stack.imgur.com/LnteV.png?s=256&g=1)
Richard Hansen
Updated on October 07, 2021Comments
-
Richard Hansen over 2 years
How do I use type hints to annotate a function that returns an
Iterable
that always yields two values: abool
and astr
? The hintTuple[bool, str]
is close, except that it limits the return value type to a tuple, not a generator or other type of iterable.I'm mostly curious because I would like to annotate a function
foo()
that is used to return multiple values like this:always_a_bool, always_a_str = foo()
Usually functions like
foo()
do something likereturn a, b
(which returns a tuple), but I would like the type hint to be flexible enough to replace the returned tuple with a generator or list or something else.-
Stevoisiak over 6 yearsPossible duplicate of How to specify multiple return types using type-hints
-
T.W.R. Cole about 5 years@StevenM.Vascellaro This is not a duplicate of that question
-
-
Richard Hansen over 7 yearsThe language specification allows returning other iterables;
foo()
could doyield True; yield "blah"
anda, b = foo()
would still work. Orfoo()
could return a list. I reworded my question to make it clear that I'm interested in hinting an arbitrary iterable, not a tuple. -
Martijn Pieters over 7 years@RichardHansen: that may well be, but type hinting only provides you with
Tuple
to express a heterogenous, fixed length return value. -
Martijn Pieters over 7 years@RichardHansen: if you want to return a list, then that's fine, but there is no facility to express that the list will have a fixed length and that specific elements in that list have specific values.
-
Richard Hansen over 7 years"What you want is not possible" is a good answer, assuming it's correct. :)
-
Martijn Pieters over 7 years@RichardHansen: I've re-checked the PEPs and documentation of
typing
andmypy
another 2 times since posting; I'm pretty confident I didn't miss anything. That said, there are several regulars here on SO with plenty of Python type hinting experience that won't hesitate to correct me if turn out to be wrong, or will post a better answer. -
Ignatius about 3 yearsSince Python 3.9,
typing.Tuple
is deprecated and the built-intuple
now supports type annotation with[]
, so you can write-> tuple[bool str]
. docs.python.org/3.9/library/typing.html#typing.Tuple -
Joel almost 3 yearsIn order to run this code in python 3.8 you may have to add
from typing import Tuple, List
-
Martijn Pieters almost 3 years@Joel: that applies to any Python 3 version; the
from typing import ...
is implied. -
sorin over 2 yearsAnd how about naming the returned tuple values in order to document them? Many functions do return or yield multiple values and we need to also document their meaning. Can can we put a name for each of them?
-
Martijn Pieters over 2 years@sorin use a NamedTuple.
-
matanster over 2 yearsI wonder if there is also syntax for type hinting the values in the caller site, i.e. type hinting a and b in:
a, b = fn()
-
Martijn Pieters over 2 years@matanster: not when assigning to multiple variables; you can annotate when there is a single variable:
res: tuple[typea, typeb] = fn()
. Unpack on a separate line:a, b = res
. Or create separate type declarations first. -
william_grisaitis about 2 years@Martijn Pieters why is
from typing
implied? since we can usegetitem
on built-in types, it seems like it's not necessary anymore (e.g.tuple[this, that]
). is this wrong? maybe it's still required in some instances? -
Martijn Pieters about 2 years@william_grisaitis: no, if you are not using the
typing.Tuple
object then you don't need to import it.