Python 3.8 will/has reached it’s end of life 1 year ago. Soon, you will be forced to upgrade as tools and libraries gradually start removing it’s support. If you have the option to upgrade to the latest Python version, take it. But especially library maintainers don’t have that luxury and still have to keep 3.9 support around. It’s been a while since all the „What’s new in Python 3.9″ articles came out. So here’s a farewell of what’s going away and hello to what can you start using instead.
Before we go into the details of what’s changing, I would recommend trying a tool called pyupgrade first to see what Python 3.9+ changes can be done for you automatically.
typing Generic (PEP 585)
While typing generics such as list[...] and dict[..., ...] have been possible since Python 3.7 thanks to from __future__ import annotations, there might be still places in the code base that use the old typing.List / typing.Dict generics. After Python 3.8, these can officially go. What can be replaced?
typing.Tuple->tupletyping.List->listtyping.Dict->dicttyping.Set->settyping.FrozenSet->frozensettyping.Type->typetyping.ContextManager->contextlib.AbstractContextManagertyping.AsyncContextManager->contextlib.AbstractAsyncContextManagertyping.Pattern->re.Patterntyping.Match->re.Match
There are also other generics that are completely new.
Operator for merging dicts (PEP 884)
{**d1, **d2} -> d1 | d2
d1.update(d2) -> d1 |= d2
New String Methods to Remove Prefixes and Suffixes (PEP 616)
You may have various local or back-ported implementations that can now be replaced with built-in ones:
removeprefix(string, prefix) -> string.removeprefix(prefix)
removesuffix(string, prefix) -> string.removesuffix(prefix)
IANA Time Zone Database in the Standard Library (PEP 615)
Time zone data has been previously available via a third-party library dateutil.tz. It is backed by the system time zone data. If it’s missing, tzdata installation is required.
dateutil.tz.gettz -> zoneinfo.ZoneInfo
Example use:
from datetime import datetime
from zoneinfo import ZoneInfo
print(datetime.now(ZoneInfo("Europe/Prague")))from datetime import datetime
from dateutil.tz import gettz
print(datetime.now(gettz("Europe/Prague")))Flexible function and variable annotations (PEP 593)
If you’re a use of the FastAPI web framework, you are likely used to the Annotated keyword already for specifying query parameters, validation, etc. Unless you are upgrading the version of FastAPI as well, only the import location changes for you:
from typing_extensions import Annotated -> from typing import Annotated
typing.Annotated doesn’t add any functionality on its own but rather allows type checkers and other tools to be smarter. You will find examples suggesting it as a way to provide more details about the type. But for such purpose, typing.TypeAlias or typing.NewType would be more suitable.
from typing import Annotated
Kilometers = Annotated[float, "kilometers"]
Seconds = Annotated[float, "seconds"]
KilometersPerHour = Annotated[float, "kilometers per hour"]
def speed(distance: Kilometers, time: Seconds) -> KilometersPerHour:
...from typing import TypeAlias
Kilometers: TypeAlias = float
Seconds: TypeAlias = float
KilometersPerHour: TypeAlias = float
def speed(distance: Kilometers, time: Seconds) -> KilometersPerHour:
...from typing import NewType
Kilometers = NewType("Kilometers", float)
Seconds = NewType("Seconds", float)
KilometersPerHour = NewType("KilometersPerHour", float)
def speed(distance: Kilometers, time: Seconds) -> KilometersPerHour:
...
Leave a Reply