admin管理员组

文章数量:1309930

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
  • 2 The Python interpreter doesn't care about type annotations. They are only for static code analysis. As to whether they differ, I'd have to leave that to someone else – roganjosh Commented Feb 2 at 11:02
  • 1 What do you think [str] represents? – jonrsharpe Commented Feb 2 at 12:24
  • 1 If you mean [str] to mean list[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 from Iterable[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:28
  • 1 In practice, Iterable implies (to both a type checker and human readers) that the function will only read but not write the value, whereas using list ensures that append, __setitem__ and other means of mutation are available. – Charles Duffy Commented Feb 2 at 12:33
  • 4 [str] is syntactically valid, but it does not specify a type hint as recognized by PEP 484: the correct spelling with defined semantics is list[str]. – chepner Commented Feb 2 at 16:16
 |  Show 5 more comments

1 Answer 1

Reset to default 4

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.

本文标签: pythonIterablestr vs strStack Overflow