

Instead of Union you can write str | int. Python 3.10 introduces the | union operator into type hinting, see PEP 604. But, while you now can use dict or list], you still may want to use the more expressive Mapping and Sequence annotations to indicate that a function won't be mutating the contents (they are treated as 'read only'), and that the functions would work with any object that works as a mapping or sequence, respectively. In Python 3.9 and up, the standard container types have all been updated to support using them in type hints, see PEP 585. """accepts an optional sequence of integers and strings """accepts an optional map with string keys and integer values"""ĭef test(a: Optional]] = None) -> None: And when only reading from a container type, you may just as well accept any immutable abstract container type lists and tuples are Sequence objects, while dict is a Mapping type: from typing import Mapping, Optional, Sequence, Unionĭef test(a: Optional] = None) -> None: So instead of dict and list, use typing.Dict and typing.List, respectively. Side note: Unless your code only has to support Python 3.9 or newer, you want to avoid using the standard library container types in type hinting, as you can't say anything about what types they must contain. The None value is not a 'subwidget id' after all, it's not part of the value, None is meant to flag the absence of a value. The refactor to move the Union into an alias was made all the much easier because Optional was used instead of Union. Support both.ĭef api_function(optional_argument: Optional = None) -> None: # subwidget ids used to be integers, now they are strings. Then documentation is improved by pulling out the Union into a type alias: from typing import Optional, Union The id should be a string, or for backwards compatibility, If optional_argument is given, it must be an id of the fooznar subwidget

Moreover, it makes it easier to move the Union part into a separate type alias, or to later remove the Optional part if an argument becomes mandatory.įor example, say you have from typing import Optional, Unionĭef api_function(optional_argument: Optional] = None) -> None: Personally, I'd stick with always using Optional when setting the type for a keyword argument that uses = None to set a default value, this documents the reason why None is allowed better. So Optional] and Union are exactly the same thing. There is technically no difference between using Optional on a Union, or just adding None to the Union. So for your two examples, you have dict and list container types, but the default value for the a keyword argument shows that None is permitted too so use Optional: from typing import Optionalĭef test(a: Optional = None) -> None: (Note: If you are targeting Python 3.10 or newer, PEP 604 introduced a better syntax, see below). Whenever you have a keyword argument with default value None, you should use Optional. stands for any valid type hint, including complex compound types or a Union of more types.


Optional is a shorthand notation for Union, telling the type checker that either an object of the specific type is required, or None is required.
