Python Typing List[Dict] vs List[dict]

Viewed 9151

In adding type hints python functions which is preferred?

from typing import List, Dict

def example_1() -> List[Dict]:
    pass

def example_2() -> List[dict]:
    pass

I know that if I wanted to specify the key and value types in the dict I'd need to use Dict, but I don't want to.

Is there any difference between the two? If so, which is preferred?

3 Answers

Since Python 3.9, the standard collections can be subscripted. The typing variants are now deprecated as a result:

tuple # typing.Tuple

list # typing.List

dict # typing.Dict

set # typing.Set

...

Importing those from typing is deprecated. Due to PEP 563 and the intention to minimize the runtime impact of typing, this deprecation will not generate DeprecationWarnings. Instead, type checkers may warn about such deprecated usage when the target version of the checked program is signalled to be Python 3.9 or newer. It's recommended to allow for those warnings to be silenced on a project-wide basis.

The deprecated functionality will be removed from the typing module in the first Python version released 5 years after the release of Python 3.9.0.

If you want to use the subscripted versions of list and dict you need to import annotations from the __future__ module, which support "Postponed Evaluation of Annotations"

This PEP proposes changing function annotations and variable annotations so that they are no longer evaluated at function definition time. Instead, they are preserved in annotations in string form.

The functionality described above can be enabled starting from Python 3.7 using the following special import:

from __future__ import annotations

So you can do something like this (tested in Python 3.8 with mypy):

from __future__ import annotations


def example() -> list[dict[str, str]]:
    return [{"1":"2"}]

In Python 3.9 this is the default behavior, so you can remove the import line as it will always have postponed annotation evaluation

def example() -> list[dict[str, str]]:
    return [{"1":"2"}]

There is no practical difference in terms of how it affects type coverage.

As a matter of style/readability, I would suggest using Dict[Any, Any] (or dict[Any, Any] if you're on a version that supports that), since it makes it more obvious to the reader that there is no type checking on the keys and values of the dict. Novices may not understand how unsafe a bare dict/Dict type is but are more likely to recognize the danger if they see the Any in there.

Related