Reputation: 485
You can mix types inside tuples or lists. Why can't you specify that in typing hints?
>>> from typing import Tuple, List
>>> t = ('a', 1)
>>> l = ['a', 1]
>>> t2: Tuple[str, int] = ('a', 1)
>>> l2: List[str, int] = ['a', 1]
TypeError: Too many parameters for typing.List; actual 2, expected 1
Upvotes: 38
Views: 32283
Reputation: 119
For people reading nowadays : If you're working with Python 3.10 and beyond, typing support has changed quite a bit. Union
can be abbreviated by |
and you don't need to import typing
anymore for most commun classes. So :
from typing import List, Union
my_list : List[Union[str, float]] = ["example", 0, 1, 2]
Is equivalent to :
my_list : list[str | float] = ["example", 0, 1, 2]
You can find every details to PEP 604, PEP 612, PEP 613 and PEP 647
However, if you want to specify the type of each elements of your list you should use a tuple instead which is what a function returns by default. In this case, your types are ordered and separated by commas :
def my_list(text : str, number : float) -> tuple[str, float] :
return text, number
If you absolutly want a list, you can go for the union notation but your type hinting is not ordered anymore and can lead to a misunderstanding :
def my_list(text : str, number : float) -> list[str | float] :
return [text, number]
Upvotes: 11
Reputation: 1549
The answer of using a List
and a Union
works in some situations, but is prone to causing bugs and is not best pracitce. There is a reason why List
doesn't allow multiple types. Let me explain.
The incorrect way of doing this (like some other answers have written) is this way.
from typing import Union, List
List[Union[str, int]]
There are two issues.
While it might solve it short term, it is not the correct way to use type hinting in python.
This is where you use a list. A list is mutable, so if you add typing, and then change the list, then the typing isn't accurate anymore. You should therefore never use List
for different types.
from typing import List
my_list = List[str]
If you actually need to type hint a list, then please use a Tuple
. A tuple is immutable and you can therefore be sure that the tuple has the correct types within.
from typing import Tuple
my_list = Tuple[str, int, int, str, int]
Upvotes: 4
Reputation: 531075
In type theory, a list is a homogenous structure containing values of one type. As such, List
only takes a single type, and every element of that list has to have that type.
However, type theory also provides sum types, which you can think of as a wrapper around exactly one value selected from some fixed set of types. A sum type is supported by typing.Union
. To specify that a list is a mix of int
and str
values, use
List[Union[str, int]]
as the type hint.
By contrast, a tuple is an example of a product type, a type consisting of a fixed set of types, and whose values are a collection of values, one from each type in the product type. Tuple[int,int,int]
, Tuple[str,int]
and Tuple[int,str]
are all distinct types, distinguished both by the number of types in the product and the order in which they appear.
Upvotes: 61
Reputation: 95948
You could use a Union
, but generally, if you can avoid it, lists should be homogenous instead of heterogeneous:
from typing import List, Union
lst: List[Union[str, int]] = [1, 'a']
myp
, at least, will accept this just fine.
This means though that your list accessors will return a Union type, often necessitating handling different possible types in any downstream functions. Accepting unions is generally less problematic.
Upvotes: 15