What’s New in Python 3.9 — A Summary of New Features
Intro
The newest Python version — Python 3.9 — was released on October 5th, 2020. In this article, I will go briefly through the new features. For more detailed information, please check the official documentation.
Timezone support
In previous python versions, you had to use third-party libraries like dateutil
or pytz
to work with timezones. Python 3.9 brings a new standard library called zoneinfo
that makes working with timezones more handy.
Standard UTC timestamp:
>>> from datetime import datetime, timezone
>>> datetime.now(tz=timezone.utc)
datetime.datetime(2020, 10, 28, 6, 47, 4, 941275, tzinfo=datetime.timezone.utc)
Zone aware timestamp:
>>> from datetime import datetime
>>> from zoneinfo import ZoneInfo>>> datetime.now(tz=ZoneInfo("Europe/Warsaw"))
datetime.datetime(2020, 10, 28, 7, 44, 59, 758797, tzinfo=zoneinfo.ZoneInfo(key='Europe/Warsaw'))
Convenient conversion between time zones:
>>> from datetime import datetime
>>> from zoneinfo import ZoneInfo>>> warsaw_now = datetime.now(tz=ZoneInfo("Europe/Warsaw"))
>>> warsaw_now
datetime.datetime(2020, 10, 28, 7, 44, 59, 758797, tzinfo=zoneinfo.ZoneInfo(key='Europe/Warsaw'))>>> warsaw_now.astimezone(ZoneInfo("America/New_York"))
datetime.datetime(2020, 10, 28, 2, 44, 59, 758797, tzinfo=zoneinfo.ZoneInfo(key='America/New_York'))
Introduced in PEP 615
Dictionaries updates
New union |
and in-place union |=
operators for built-in dict
class were introduced.
union |
- dictionary merge complement do {**dict1, **dict2}
Merging two dictionaries with unpacking (**
) and union (|
) operators:
>>> english = {1: "one", 2: "two", 3: "three"}
>>> spanish = {2: "duo", 3: "Tres", 4: "cuatro"}>>> {**spanish, **english} # unpacking syntax
{2: 'two', 3: 'three', 4: 'cuatro', 1: 'one'}>>> spanish | english # union
{2: 'two', 3: 'three', 4: 'cuatro', 1: 'one'}
>>> english
{1: 'one', 2: 'two', 3: 'three'}
>>> spanish
{2: 'duo', 3: 'Tres', 4: 'cuatro'}
in-place union |=
- dictionary update complement to dict.update
Updating dictionary with update()
method:
>>> english = {1: "one", 2: "two", 3: "three"}
>>> spanish = {2: "duo", 3: "Tres", 4: "cuatro"}’>>> english.update(spanish)
>>> english
{1: 'one', 2: 'duo', 3: 'Tres', 4: 'cuatro'}
Updating dictionary with in-lace union |=
operator:
>>> english = {1: "one", 2: "two", 3: "three"}
>>> spanish = {2: "duo", 3: "Tres", 4: "cuatro"}’>>> english |= spanish
>>> english
{1: 'one', 2: 'duo', 3: 'Tres', 4: 'cuatro'}
The significant advantage of using new operators is that they work on dictionary-like types and keep the type after a merge or update:
>>> from collections import defaultdict>>> english = defaultdict(lambda: "", {1: "one", 2: "two", 3: "three"})
>>> spanish = defaultdict(lambda: "", {2: "duo", 3: "Tres", 4: "cuatro"})>>> {**spanish, **english} # unpacking syntax
{2: 'two', 3: 'three', 4: 'cuatro', 1: 'one'}
>>> spanish | english # union
defaultdict(<function <lambda> at 0x10925e160>, {2: 'two', 3: 'three', 4: 'cuatro', 1: 'one'})
Introduced in PEP-584
Improved type hinting
Annotated type hints
The type typing.Annotated
was introduced to decorate existing types with context-specific metadata.
from typing import Annotateddef force(
mass: Annotated[float, "kg"],
acceleration: Annotated[float, "m/s^2"]
) -> Annotated[float, "Newtons"]:
"""Calculate force"""
return mass * acceleration
Type hinting generics
There is no need to import capitalIzed built-in collection types (e.g. list
or dict
) from the typing
library anymore.
from typing import Listnames: List[str]
They can be used directly now:
names: list[str]
Introduced in PEP 593 and PEP 585
New string methods
Removing prefixes or suffixes from the string hasn’t been convenient in Python so far. The method .strip(“python”)
treats “python”
not as a substring to be removed but as a set of characters to be stripped from the beginning and end of the string.
>>> "there are new methods in python".strip(" python")
'ere are new methods i'
It is not hard to write a function to strip the beginning or the end of the string, but new Python introduces convenient string methods .removesuffix()
and “.removeprefix()” to handle this.
>>> "there are a new methods in python".removeprefix("there are ")
'a new methods in python'
>>> "there are a new methods in python".removesuffix(" python")
'there are a new methods in'
Introduced in PEP 616
New math methods
To easily calculate the Greatest Common Divisor (GCD) and the Least Common Multiple (LCM), new methods were introduced in the math
library.
The great common divisor is the largest number that divides all numbers passed as arguments.
>>> math.gcd(729, 162)
81
>>> math.gcd(729, 162, 9)
9
The least common multiple is the smallest number that can be divided by all numbers passed as arguments.
>>> math.lcm(18, 81)
162
>>> math.lcm(18, 81, 162)
162
Other features
Here are some other changes introduced in Python 3.9:
- a more powerful parser based on PEG (parsing expression grammar) PEP 617
- new HTTP status codes — 103 (Early Hints) and 425 (Too Early)
- relaxed grammar restrictions on decorators (PEP 614)
- optimized signal handling in multithreaded applications.
- a new
graphlib
module with the implementation of a topological sort of a graph
For a full list of new features, check the official documentation.
Wrapping up
The newest Python version brings some interesting things to the table. They have been around for some time in beta-versions, so most of the bugs are eliminated. It is definitely worth checking out. However, you have to be aware that some libraries may not support Python 3.9 yet.
This blog post was originally published at https://www.polidea.com/blog/