Declaring literal variables
You must explicitly add an annotation to a variable to declare that it hasa literal type:
- a: Literal[19] = 19
- reveal_type(a) # Revealed type is 'Literal[19]'
In order to preserve backwards-compatibility, variables without this annotationare not assumed to be literals:
- b = 19
- reveal_type(b) # Revealed type is 'int'
If you find repeating the value of the variable in the type hint to be tedious,you can instead change the variable to be Final
(see Final names, methods and classes):
- from typing import Final, Literal
- def expects_literal(x: Literal[19]) -> None: pass
- c: Final = 19
- reveal_type(c) # Revealed type is 'Literal[19]?'
- expects_literal(c) # ...and this type checks!
If you do not provide an explicit type in the Final
, the type of c
becomescontext-sensitive: mypy will basically try “substituting” the original assignedvalue whenever it’s used before performing type checking. This is why the revealedtype of c
is Literal[19]?
: the question mark at the end reflects thiscontext-sensitive nature.
For example, mypy will type check the above program almost as if it were written like so:
- from typing import Final, Literal
- def expects_literal(x: Literal[19]) -> None: pass
- reveal_type(19)
- expects_literal(19)
This means that while changing a variable to be Final
is not quite the same thingas adding an explicit Literal[…]
annotation, it often leads to the same effectin practice.
The main cases where the behavior of context-sensitive vs true literal types differ arewhen you try using those types in places that are not explicitly expecting a Literal[…]
.For example, compare and contrast what happens when you try appending these types to a list:
- from typing import Final, Literal
- a: Final = 19
- b: Literal[19] = 19
- # Mypy will chose to infer List[int] here.
- list_of_ints = []
- list_of_ints.append(a)
- reveal_type(list_of_ints) # Revealed type is 'List[int]'
- # But if the variable you're appending is an explicit Literal, mypy
- # will infer List[Literal[19]].
- list_of_lits = []
- list_of_lits.append(b)
- reveal_type(list_of_lits) # Revealed type is 'List[Literal[19]]'