How to properly function annotate / type hint a list of strings

Question:

I am trying to figure out how to properly function annotate or type hint a list of strings. For example, if I had a function like this:

def send_email(self, from_address: str, to_addresses: list[str]):
    pass

to_addresses should be a list of strings. But when I try to use that annotation I get the following error in my Python 3.4.3 interpreter:

TypeError: 'type' object is not subscriptable

I am positive the list[str] is causing the issue, because if I change it to str the error goes away, but that doesn’t properly reflect my intentions for the parameter.

Asked By: gnychis

||

Answers:

Python 3.4 doesn’t specify a format for its function annotations, it merely provides a mechanism that allows you to use any expression as the annotation. How the annotations are interpreted is up to you and the libraries you use.

Python 3.5 standardizes the way function annotations are used for type hinting, as documented in PEP 484. To annotate a list of strings, you use List[str], where List is imported from the typing module. You can also use Sequence[str] if your function accepts any list-like sequence, or Iterable[str] for any iterable.

Starting with Python 3.9, you can use list[str] as a type annotation, which doesn’t require importing anything.

Answered By: interjay

In Python 3.9+, list (with a lowercase l) can be used in type annotations and your code should work as is. On older versions of Python you need to import typing.List and use it instead

from typing import List

to_addresses: List[str]

Note the capital L.

You might want to consider something more specific, e.g.

import typing
Address = typing.NewType("Address")

See NewType docs

The static type checker will treat the new type as if it were a subclass of the original type

Answered By: Martin Thoma

This syntax is now valid in Python 3.9+:

In type annotations you can now use built-in collection types such as list and dict as generic types instead of importing the corresponding capitalized types (e.g. List or Dict) from typing.

Prior to 3.9 though, you need to use the imported List or in Python 3.7+ you can add

from __future__ import annotations

at the top of your file, which allows using list[int] (for example). Note though, this import only affects annotations:

from __future__ import annotations only affects annotations — just the things after the colon. It makes it so that annotations are never evaluated

It still doesn’t allow list[int] in arbitrary contexts.

Answered By: Carcigenicate
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.