Table of contents
Open Table of contents
Overview
Python 3.10+ introduced structural pattern matching, improved error messages, and significant typing enhancements. This post covers the key additions that make Python more expressive and type-safe.
Version 3.10
Structural Pattern Matching
The most significant addition — match/case statements with destructuring:
def process_command(command: str) -> str:
match command.split():
case ["quit"]:
return "Goodbye"
case ["go", direction]:
return f"Going {direction}"
case ["get", item] if item != "sword":
return f"Picked up {item}"
case _:
return "Unknown command"
Class Pattern Matching
from dataclasses import dataclass
@dataclass
class Point:
x: float
y: float
def classify_point(point: Point) -> str:
match point:
case Point(x=0, y=0):
return "origin"
case Point(x=0, y=y):
return f"on y-axis at {y}"
case Point(x=x, y=0):
return f"on x-axis at {x}"
case Point():
return "elsewhere"
Parenthesized Context Managers
with (
open("input.txt") as infile,
open("output.txt", "w") as outfile,
):
outfile.write(infile.read())
Better Error Messages
Python 3.10 dramatically improved error messages with precise locations and suggestions:
# Before: SyntaxError: invalid syntax
# After: SyntaxError: '{' was never closed
Union Type Syntax with |
def process(value: int | str) -> str:
return str(value)
Version 3.11
Exception Groups and except*
Handle multiple exceptions simultaneously:
try:
async with asyncio.TaskGroup() as tg:
tg.create_task(risky_operation_1())
tg.create_task(risky_operation_2())
except* ValueError as eg:
for exc in eg.exceptions:
print(f"ValueError: {exc}")
except* TypeError as eg:
for exc in eg.exceptions:
print(f"TypeError: {exc}")
tomllib — Built-in TOML Parsing
import tomllib
with open("pyproject.toml", "rb") as f:
config = tomllib.load(f)
print(config["project"]["name"])
Performance Improvements
Python 3.11 is 10-60% faster than 3.10 thanks to the Faster CPython project, including specializing adaptive interpreter and lazy frame objects.
Fine-Grained Error Locations
Tracebacks now point to the exact expression that caused the error:
# Traceback:
# x['a']['b']['c']['d']
# ^^^^
# TypeError: 'NoneType' is not subscriptable
Version 3.12
Type Parameter Syntax
New syntax for declaring generics without importing from typing:
# Before
from typing import TypeVar, Generic
T = TypeVar('T')
class Stack(Generic[T]):
...
# After (3.12+)
class Stack[T]:
def __init__(self) -> None:
self._items: list[T] = []
def push(self, item: T) -> None:
self._items.append(item)
def pop(self) -> T:
return self._items.pop()
Type Aliases with type Statement
type Point = tuple[float, float]
type Matrix[T] = list[list[T]]
type RecursiveList[T] = T | list["RecursiveList[T]"]
F-String Improvements
F-strings can now contain any valid Python expression, including nested f-strings, backslashes, and comments:
# Nested f-strings
print(f"result: {f'{value:.2f}' if value else 'N/A'}")
# Multiline expressions
message = f"Hello {
name # inline comment OK
.upper()
}"
@override Decorator
from typing import override
class Parent:
def process(self) -> None: ...
class Child(Parent):
@override
def process(self) -> None: # type checker verifies parent has this method
...
Version 3.13
Improved Interactive Interpreter
New REPL with multiline editing, color output, and history navigation (based on PyPy’s).
Experimental Free-Threaded Mode
Optional build without the GIL (--disable-gil), enabling true parallel threads:
python3.13t -X gil=0 my_script.py
Experimental JIT Compiler
Copy-and-patch JIT compiler — opt-in, providing modest speedups as a foundation for future optimization.
typing.ReadOnly for TypedDict
from typing import ReadOnly, TypedDict
class Config(TypedDict):
name: ReadOnly[str]
debug: bool
config: Config = {"name": "app", "debug": True}
# config["name"] = "other" # type error
config["debug"] = False # OK
Deprecation of typing.NamedTuple Old Syntax
New recommended pattern:
from typing import NamedTuple
class Point(NamedTuple):
x: float
y: float
label: str = "default"
Key Takeaways
- Pattern matching — Python’s most powerful control flow addition since generators
- Type parameter syntax — generics finally feel native (
class Stack[T]) - Performance — consistent speedups across 3.11-3.13 (Faster CPython, JIT foundations)
- Error experience — dramatically better tracebacks and error messages
- Typing maturity —
typealiases,@override,ReadOnly, union|syntax
Related Katas
- Kata: Factory Pattern — pattern matching for type dispatch
- Kata: Binary Search Tree —
class Node[T]with type parameters - Kata: Linked List —
__iter__protocol and generators - Kata: Decorator Pattern — native Python decorators