What is the correct type hint for an empty list?

Question:

What is the correct type hint for x = []?

The type checker in my PyCharm editor flagged this as an error:

labelframes: List[ttk.LabelFrame] = []

‘Optional’ is not an option as in:

labelframes: List[Optional[ttk.LabelFrame]] = []

because the documentation for typing.Optional states that this is equivalent to:

labelframes: List[Union[ttk.LabelFrame, None]] = []

and [None] is not [].

I ought to mention that PyCharm doesn’t like this either:

labelframes: List[Union[ttk.LabelFrame, None]] = [None]

Whatever type hint I try. PyCharm flags it as an error with,
“Expected to return my type hint here, got no return,” so I tried:

labelframes: Optional[List[ttk.LabelFrame, None]] = []

That didn’t work.

I am aware that PEP 526 has numerous examples which follow the pattern:

x: List[str] = []
Asked By: lemi57ssss

||

Answers:

Looking at PEP 484, specifically the section on type comments (the precursor to variable annotations) this does indeed seem like a bug with PyCharm’s checker.

Quoting from the PEP:

In non-stub code, there is a similar special case:

from typing import IO

stream = None  # type: IO[str]

Type checkers should not complain about this (despite the value None not matching the given type), nor should they change the inferred type to Optional[...] (despite the rule that does this for annotated arguments with a default value of None ). The assumption here is that other code will ensure that the variable is given a value of the proper type, and all uses can assume that the variable has the given type.

So, in a similar fashion, type-checkers (as mypy currently does), should not complain about the fact that the initializing value you provide doesn’t strictly match the annotation.

Let’s first write sample code for an empty list and check it using mypy.

from typing_extensions import reveal_type

l = []
reveal_type(l)

Now let’s run it in the shell, as below.

$ mypy test.py

test.py:4: error: Need type annotation for "l" (hint: "l: List[<type>] = ...")
test.py:6: note: Revealed type is "builtins.list[Any]"
Found 1 error in 1 file (checked 1 source file)

Now pay attention to the second line as it says that the type is List[Any].

Lets make changes and re-run

from typing import Any, List
from typing_extensions import reveal_type

l : List[Any] = []

reveal_type(l)

And now run mypy.

$ mypy test.py

test.py:6: note: Revealed type is "builtins.list[Any]"
Success: no issues found in 1 source file
Answered By: Lawhatre