I'm trying to understand the difference between:
from typing import Iterable
def func(self, stuff: Iterable[str]) -> str:
and:
def func(self, stuff: [str]) -> str:
Are both statements valid? Do they give the same information to Python (3.12+) interpreter?
This question is related but doesn't answer my specific problem about the Iterable keyword.
I'm trying to understand the difference between:
from typing import Iterable
def func(self, stuff: Iterable[str]) -> str:
and:
def func(self, stuff: [str]) -> str:
Are both statements valid? Do they give the same information to Python (3.12+) interpreter?
This question is related but doesn't answer my specific problem about the Iterable keyword.
Share Improve this question edited Feb 2 at 16:00 suizokukan asked Feb 2 at 10:49 suizokukansuizokukan 1,3794 gold badges19 silver badges34 bronze badges 10 | Show 5 more comments1 Answer
Reset to default 4At runtime, both statements are valid, but they are different:
>>> from typing import Iterable, get_type_hints
>>> def f1(self, stuff: Iterable[str]) -> str: ...
>>> def f2(self, stuff: [str]) -> str: ...
>>> get_type_hints(f1)
{'stuff': typing.Iterable[str], 'return': <class 'str'>}
>>> get_type_hints(f2)
{'stuff': [<class 'str'>], 'return': <class 'str'>}
Function annotations like these don't do any magic. They're plain Python expressions (but if there's a from __future__ import annotations
, then these expressions are converted to strings).
Static type-checkers will accept the first definition, but will reject the second one. Mypy, for example, will report
main.py:4: error: Bracketed expression "[...]" is not valid as a type [valid-type]
main.py:4: note: Did you mean "List[...]"?
Found 1 error in 1 file (checked 1 source file)
It's easy to see this for yourself on mypy playground.
Pyright, another popular static type-checker that's used by Pylance in VSCode, will report
List expression not allowed in type expression
Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
basedpyright playground
In fact, all static-type checkers will reject it. This is because this particular syntax that you're using, isn't part of the official typing specification, which all type-checkers follow (although mypy sometimes deviates from it).
You can find guides, reference docs, and the full typing specification on typing.readthedocs.io.
[str]
represents? – jonrsharpe Commented Feb 2 at 12:24[str]
to meanlist[str]
, (1) I'm not sure it actually does (and in any event the latter is much more conventional), but (2) that's very definitely a different thing fromIterable[str]
. Lots of things that aren't lists are still iterable, whereas only a list is a list. – Charles Duffy Commented Feb 2 at 12:28Iterable
implies (to both a type checker and human readers) that the function will only read but not write the value, whereas usinglist
ensures thatappend
,__setitem__
and other means of mutation are available. – Charles Duffy Commented Feb 2 at 12:33[str]
is syntactically valid, but it does not specify a type hint as recognized by PEP 484: the correct spelling with defined semantics islist[str]
. – chepner Commented Feb 2 at 16:16