Python 3.11 is out - All important features
Learn what's new in Python 3.11. It's can be up to 60% faster and includes several other changes.
Python 3.11 is out! Learn about all important changes in this article.
You can also watch the video here:
Faster CPython
It got faster! Python 3.11 is on average 25% faster than 3.10. Depending on your workload, the speedup could be up to 10-60% faster. Learn more about the speed improvements here.
Better Error Messages
It got better error messages. The interpreter will now point to the exact expression that caused the error, instead of just the line.
Traceback (most recent call last):
File "distance.py", line 11, in <module>
print(manhattan_distance(p1, p2))
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "distance.py", line 6, in manhattan_distance
return abs(point_1.x - point_2.x) + abs(point_1.y - point_2.y)
^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'x'
add_note()
for Exceptions
The add_note()
method is added to BaseException. It lets you add additional information which then appears in the traceback.
try:
raise TypeError
except Exception as e:
e.add_note("This is a note")
raise
# ---
Traceback (most recent call last):
File "/main.py", line 2, in <module>
raise TypeError
TypeError
This is a note
Exception Groups and except*
ExceptionGroup
and except*
were added. They make it possible to group exceptions and raise them together, so you can raise and handle multiple unrelated exceptions simultaneously.
eg = ExceptionGroup(
"one",
[
TypeError(1),
ExceptionGroup(
"two",
[TypeError(2), ValueError(3)]
),
ExceptionGroup(
"three",
[OSError(4)]
)
]
)
try:
raise eg
except* ValueError as e:
print(f"Handling ValueError: {e.exceptions}")
except* TypeError as e:
print(f"Handling TypeError: {e.exceptions}")
except* OSError as e:
print(f"Handling OSError: {e.exceptions}")
Type Hints features
New features related to Type Hints and the typing module were added. This includes the LiteralString
, the Required
and NotRequired
types, and the Self
type with a capital S.
LiteralString
The new LiteralString
annotation may be used to indicate that a function parameter can be of any literal string type. Type checkers can then enforce that sensitive functions, such as those that execute SQL statements are called only with static arguments, providing protection against injection attacks.
from typing import LiteralString
def run_query(sql: LiteralString) -> None:
...
Required, NotRequired
Required
and NotRequired
provide a straightforward way to mark whether individual items in a TypedDict
must be present. Those two definitions are equivalent, so in this case, title has to be defined.
from typing import TypedDict, Required, NotRequired
class Movie(TypedDict):
title: str
year: NotRequired[int]
m1: Movie = {"title": "Black Panther", "year": 2018} # OK
m2: Movie = {"title": "Star Wars"} # OK (year is not required)
m3: Movie = {"year": 2022} # ERROR (missing required field title)
# The following definition is equivalent:
class Movie(TypedDict, total=False):
title: Required[str]
year: int
Self
And the new Self
annotation provides a simple and intuitive way to annotate methods that return an instance of their class. Common use cases include alternative constructors provided as classmethods, and enter methods that return self:
from typing import Self
class MyLock:
def __enter__(self) -> Self:
self.lock()
return self
class MyInt:
@classmethod
def fromhex(cls, s: str) -> Self:
return cls(int(s, 16))
New tomllib module
And a whole new module was added, the tomllib
module, which adds support for parsing TOML files.
import tomllib
with open("pyproject.toml", "rb") as f:
data = tomllib.load(f)
# Or from a string:
toml_str = """
python-version = "3.11.0"
python-implementation = "CPython"
"""
data = tomllib.loads(toml_str)
New asyncio TaskGroup
The asyncio TaskGroup class was added, which is an asynchronous context manager holding a group of tasks that are awaited when the context manager exits. For new code this is recommended over using create_task() and gather() directly.
async def main():
async with asyncio.TaskGroup() as tg:
task1 = tg.create_task(some_coro(...))
task2 = tg.create_task(another_coro(...))
print("Both tasks have completed now.")
New math functions
The math module got 2 new cool functions:
math.exp2
which returns 2 raised to the power of x, andmath.cbrt
which returns the the cube root of x.
import math
print(math.exp2(4))
# 16.0
print(math.cbrt(8))
# 2.0
Conclusion
These are the most important changes. To read about all changes check out this link: