*Memo:
- My post explains type hints (2).
- My post explains type hints (3).
- My post explains type hints (4).
- My post explains type hints (5).
- My post explains type hints (6).
- My post explains type hints (7).
A type hint:
- is the optional static type created by single or multiple types for a variable, or function parameter or return value:
- There are a non-union type and union type because by Python interpreter at runtime which is more important program than type checkers at unruntime, a single type isn't interpreted as Union while multiple types are interpreted as
Union:- I use the word runtime instead of execution time, running time, etc to mean the time when Python code is running.
- I use the word unruntime instead of compile time, static analysis time, etc to mean the time before runtime.
- There are a non-union type and union type because by Python interpreter at runtime which is more important program than type checkers at unruntime, a single type isn't interpreted as Union while multiple types are interpreted as
- is for the (static) type checkers such as mypy, pyright, pyrefly, ty, etc so error doesn't occur with Python interpreter even if a type hint is wrong:
- should be used as specific as possible.
- can be done with
':', with one or more types and with or without'|'and'[]'.
Basically, I used mypy --strict for the experiments.
mypy --strict for the experiments. *mypy can be installed with pip install mypy.
A type hint can be done with ':', with one or more types and with or without '|' and '[]' as shown below:
*Memo for '|':
-
'|'can be used from Python 3.10. - The type of
'|'is Union at runtime:-
Unionis an old way and can still be used.
-
-
UnionType is the alias of
Unionfrom Python 3.14 but currently, using it with mypy gives error as the issue:-
UnionTypeis used as one unruntime type which reveal_type() shows:-
reveal_type()can show both a runtime and unruntime type while type() can show only a runtime type.
-
-
- To set one or more types and
None, Optional can also be used from Python 3.10: - For
UnionandUnionType:- The 1st arguments are
*types(Required-Type:Type):- It's one or more types.
- Don't use any keywords like *types=, types=, etc.
-
Union[str, int, None],UnionType[str, int, None]andstr | int | Noneare equivalent.
- The 1st arguments are
- For
Optional:- The 1st argument is
type(Required-Type:Type):- It's a type.
- Don't use
type=.
-
Optional[str],str | None,Union[str, None]andUnionType[str, None]are equivalent.
- The 1st argument is
- At runtime, the type of:
- a single type is the non-union type which isn't
Unioneven if usingUnion,UnionTypeandOptional. - multiple types is the union type which is
Unioneven if usingUnionTypeandOptional.
- a single type is the non-union type which isn't
- At unruntime, many representations are used whether single or multiple types.
*Memo for '[]':
-
'[]'can be used for iterables(a list, tuple, set, etc),Union,UnionType,Optional, Callable(a function, generator or method), etc. -
'[]'is required with--strictbut optional without--strict.
# from typing import Union
# from types import UnionType
v: str = 'Hello' # No error
# v: Union[str] = 'Hello' # No error
# v: UnionType[str] = 'Hello' # Error
# Equivalent
v = 23
v = None
# Error
# from typing import Union, Optional
v: str | int | None = 'Hello'
# v: Union[str, int, None] = 'Hello'
# v: Optional[str | int] = 'Hello'
# Equivalent
v = 23
v = None
# No error
v = 2.3
# Error
# from typing import Union
v: list[int | str] = [0, 'A', 1, 'B', 2]
# v: Union[list[Union[int, str]]] = [0, 'A', 1, 'B', 2]
# Equivalent
v.append('C')
# No error
v.append(3.4)
v = {0, 1, 2}
# Error
# from typing import Union, Optional
def func(name: str, age: int | None = None) -> str | None:
# def func(name: Union[str], age: Union[int, None] = None) -> Union[str]:
# def func(name: str, age: Optional[int] = None) -> str:
return f'Name:{name}, Age:{age}' # Equivalent
print(func('John')) # No error
print(func(name='John')) # No error
print(func('John', 28)) # No error
print(func(name='John', age=28)) # No error
from typing import Any, Union, Optional, reveal_type
# The runtime type of single type with `type()`
print(type(int)) # <class 'type'>
print(type(None)) # <class 'NoneType'>
print(type(Any)) # <class 'typing._AnyMeta'>
print(type(Union[int])) # <class 'type'>
print(type(Optional[None])) # <class 'type'>
# The runtime type of multiple types with `type()`
print(type(int | float)) # <class 'typing.Union'>
print(type(None | Any)) # <class 'typing.Union'>
print(type(Union[int, float])) # <class 'typing.Union'>
print(type(Optional[int])) # <class 'typing.Union'>
# The runtime type of single type with `reveal_type()`
reveal_type(int) # type
reveal_type(None) # NoneType
reveal_type(Any) # _AnyMeta
reveal_type(Union[int]) # type
reveal_type(Optional[None]) # type
# The runtime type of multiple types with `reveal_type()`
reveal_type(int | float) # Union
reveal_type(None | Any) # Union
reveal_type(Union[int, float]) # Union
reveal_type(Optional[int]) # Union
# The unruntime type of single type with `reveal_type()`
reveal_type(int)
# Overload(def (builtins.str | _collections_abc.Buffer |
# typing.SupportsInt | typing.SupportsIndex =) -> builtins.int,
# def (builtins.str | builtins.bytes | builtins.bytearray,
# base: typing.SupportsIndex) -> builtins.int)"
reveal_type(None) # None
reveal_type(Any) # def () -> typing.Any
reveal_type(Union[int]) # typing._SpecialForm
reveal_type(Optional[None]) # typing._SpecialForm
# The unruntime type of multiple types with `reveal_type()`
reveal_type(int | float)
# types.UnionType | Overload(def (builtins.str |
# _collections_abc.Buffer | typing.SupportsInt |
# typing.SupportsIndex =) -> builtins.int,
# def (builtins.str | builtins.bytes |
# builtins.bytearray, base: typing.SupportsIndex) -> builtins.int)
reveal_type(None | Any) # types.UnionType | def () -> typing.Any
reveal_type(Union[int, float]) # typing._SpecialForm
reveal_type(Optional[int]) # typing._SpecialForm
Top comments (0)