Yes, you can make the number of items in a tuple type hint flexible.
From Python 3.9 and on you can do:
def func(var: tuple[int, ...]):
pass
Before Python 3.9 you would do:
from typing import Tuple
def func(var: Tuple[int, ...]):
pass
From the docs: https://docs.python.org/3/library/stdtypes.html#tuple
Answer from aaron on Stack OverflowTo specify a variable-length tuple of homogeneous type, use literal ellipsis, e.g.
tuple[int, ...]. A plaintupleis equivalent totuple[Any, ...], and in turn totuple.
Tuple-like typing for lists in type hints
Type Hints, can you indicate various types inside a list?
Correct way to typehint an argument that only accepts list, set, or tuple - Typing - Discussions on Python.org
Question regarding type-hinting Collection types
Yes, you can make the number of items in a tuple type hint flexible.
From Python 3.9 and on you can do:
def func(var: tuple[int, ...]):
pass
Before Python 3.9 you would do:
from typing import Tuple
def func(var: Tuple[int, ...]):
pass
From the docs: https://docs.python.org/3/library/stdtypes.html#tuple
To specify a variable-length tuple of homogeneous type, use literal ellipsis, e.g.
tuple[int, ...]. A plaintupleis equivalent totuple[Any, ...], and in turn totuple.
Starting with PEP 585 it is possible to use builtin typings without importing the typing module, so starting with Python 3.9, Tuple[...] has been deprecated in favor of tuple[...]. e.g.
def func(var: tuple[int, ...]):
pass
If I have a list that I know will have a certain type of object in the first element and a different type in the second. For instance, if I have a function that combines two lists and returns a lists of lists like so:
names = ["Brad Pitt", "Leonardo DiCaprio", "Henry Cavill", "Hugo Weaving"]
grades = [85,32,95,90]
def combine_lists():
names_grades = []
for i in range(0,4):
names_grades.append(names[i],grades[i])
return names_gradesIs it possible to type hint the return type so that it reflects the types in the list, something like this:
def combine_lists() ->List(str,int):
The point of this is that later I would be aware of the type I'm accessing when I try to read a specific element of the list for example:
list_of_grades = combine_lists()x = list_of_grades[0] #I want to know this is a string
I'm trying to make sense of the current type-hinting convention regarding Collection types. For simplicity's sake, I'll use list, tuple and dict, but that applies to any of their variant. Note that none of the following lines of code actually raise an error when run. Here's my question:
When someone writes:
var: str | int
What I read is obviously that 'var' is either a string OR an integer.
Again, when someone writes:
lst: list[str]
What I read is obviously that 'lst' is a list that contains ONLY strings.
So, logic says that here:
list[str | int]
It means that it's a list that contains ONLY strings OR ONLY integers. Right? And in this following case:
list[str, int]
it means that it's a list that contains strings AND/OR integers. Perhaps would it make more sense if it used & instead of , but whatever. Hopefully I'm making sense.
However, when checking the types using mypy, I find out that list[str, int] is not conventional, and that rather you should use list[str | int] for both cases. My code editor also says this, and yours probably does too.
Now take a similarly-structured type, tuple. By similarly-structured, I mean that you access and iterate through tuples the same way, in fact they are both Sequence types. The thing with tuple is that its args are index sensitive. I understand why this is the case and why it makes sense (because of immutability), but what doesn't make sense to me is why mypy is fine now with the comma notation with tuple but not list.
tpl: tuple[str, int] = ("", 0) # fine
tpl: tuple[str, int] = (0, "") # not fine
tpl: tuple[str | int] = (0, "") # not fine
tpl: tuple[str | int] = (0, ) # fine
tpl: tuple[str | int] = ("", ) # fineLast but not least, dict. Everybody knows that Mapping types are different from Sequence types in the way you access, set or delete their items. So why is the typing convention this:
dict[str, int] # comma notation like tuple
and not:
dict[str: int] # Mapping specific notation
The latter makes much more sense and is more readable to me, and makes the distinction between Sequence types and Mapping types. Furthermore, the use of commas in Mapping types kinda looks like you can insert as many of them as you want, just like tuple?
tpl: tuple[str, int] = ("", 0) # this is fine
tpl: tuple[str, int, bool] = ("", 0, False) # this is fine
dct: dict[str, int, bool] = {"": 0: False} # but this is not fineI know that slices are not hashable for a reason, and that dict[str: int] notation kinda implies that they are, but again, the interpreter will raise no errors if you do this, much like if you write list[str, int], so I don't see the problem.
Is there an actual, good reason why this is the way it is?