Reputation: 1379
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.
Upvotes: -1
Views: 181
Reputation: 3315
At 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)
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.
Upvotes: 4