suizokukan
suizokukan

Reputation: 1379

Iterable[str] vs [str]

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

Answers (1)

Joren
Joren

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)

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.

Upvotes: 4

Related Questions