Image by Martin Thoma
Python keeps developing via Python Enhancement Proposals (PEPs). PEP 586 added a feature I love: Literal Types 😍
After reading this article you will know how to use that feature.
If you happen to be new to type annotations, I recommend reading my introduction to type annotations in Python.
The Literal
type needs at least one parameter, e.g. Literal["foo"]
. That means that the annotated variable can only take the string "foo"
. If you want to accept "bar"
as well, you need to writeLiteral["foo", "bar"]
.
A complete example:
from typing import Literal
# If you are on Python 3.7 and upgrading is not an option,
# $ pip install typing_extensions
# to install the backport. Then import it:
# from typing_extensions import Literaldef parse_bool_str(
text: str,
default: Literal["raise", False] = "raise"
) -> bool:
if text.lower() in ["y", "yes", "true", "1", "on"]:
return True
if text.lower() in ["n", "no", "false", "0", "off"]:
return False
if default == "raise":
raise ValueError(f"It's unclear: {text}")
return False
We could also have annotated default
with Union[str, bool]
, but that would allow a big range of other values and different behavior.
Please note that you need to run mypy
during development (best in your CI pipeline) to find such issues. It will NOT help you during runtime. Read my introduction to type annotations in Python for more about that.
Instead of using a Literal type, you could use an enum:
def parse_bool_str(
text: str,
default: DefaultValues = DefaultBehaviour.RAISE
) -> bool:
if text.lower() in ["y", "yes", "true", "1", "on"]:
return True
if text.lower() in ["n", "no", "false", "0", "off"]:
return False
if default == DefaultBehaviour.RAISE:
raise ValueError(f"It's unclear: {text}")
return False
You can see that this changes the code in multiple places. For this reason, it might be harder to use Enums for type annotations in an existing codebase.
When it comes to (de)serialization and data validation, I recently fell in love with pydantic 😍
Let’s test how pydantic deals with Literals:
It works like a charm 🎉