New Syntax and Features#
Python 3.10 through 3.13 added syntax and stdlib features that change how production code is written: structural pattern matching, modern union types, exception groups, improved error messages, type parameter syntax, and experimental free-threading. This page focuses on practical, interview-relevant additions for Python 3.10+.
How to use this page
Target Python 3.11+ for the best balance of features and support. Cross-reference Type Hints and Annotations for typing features and Global Interpreter Lock for free-threading internals.
At a glance
| Track | Python Advanced → New Python Features and Enhancements |
| Sections | 16 major topics |
| Outline | Use the right-hand TOC to jump |
Topics: Version feature matrix · Structural pattern matching (3.10+) · Union types with | (3.10+) · Parenthesized context managers (3.10+) · dataclass improvements · Exception groups and except* (3.11+) · Self type (3.11+) · tomllib — read TOML from stdlib (3.11+) · … (+8 more)
- Version feature matrix
- Structural pattern matching (3.10+)
- Union types with
|(3.10+) - Parenthesized context managers (3.10+)
dataclassimprovements- Exception groups and
except*(3.11+) Selftype (3.11+)tomllib— read TOML from stdlib (3.11+)- Improved error messages (3.11+)
- Type parameter syntax (3.12+)
typing.override(3.12+)- Walrus operator
:=(3.8+, still essential) … and 4 more sections
Version feature matrix#
| Feature | Version | PEP |
|---|---|---|
match / case |
3.10 | 634 |
X \| Y union types |
3.10 | 604 |
dataclass(kw_only=True) |
3.10 | — |
Exception groups / except* |
3.11 | 654 |
Self type |
3.11 | 673 |
tomllib (stdlib TOML) |
3.11 | 680 |
| Fine-grained error locations | 3.11 | 657, 678 |
typing.override |
3.12 | 698 |
Type parameter syntax class C[T] |
3.12 | 695 |
| Improved f-string parsing | 3.12 | 701 |
| Per-interpreter GIL (optional) | 3.12 | 684 |
Free-threaded build (--disable-gil) |
3.13 | 703 |
| Experimental JIT | 3.13 | 744 |
| Improved interactive REPL | 3.13 | — |
Structural pattern matching (3.10+)#
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
def describe(value) -> str:
match value:
case 0:
return "zero"
case [x, y]:
return f"pair: {x}, {y}"
case {"type": "user", "name": str(name)}:
return f"user {name}"
case Point(x=0, y=y):
return f"on y-axis at {y}"
case Point(x, y) if x == y:
return f"diagonal at {x}"
case _:
return "unknown"
| Pattern | Matches |
|---|---|
| Literals | case 42:, case "ok": |
| Capture | case x: binds x |
| Sequence | case [a, b]: length 2 list |
| Mapping | case {"key": val}: key present |
| Class | case Point(x, y): destructuring |
| Guard | case x if x > 0: |
| Wildcard | case _: default |
Use match for structured data
Excellent for AST nodes, JSON shapes, and command dispatch — clearer than long if/elif chains.
OR patterns and aliases#
match status:
case 200 | 201 | 204:
return "success"
case code if 400 <= code < 500:
return "client error"
Union types with | (3.10+)#
Replaces Union[str, int, None] from typing — preferred in modern codebases. See Type Hints and Annotations.
Parenthesized context managers (3.10+)#
from contextlib import contextmanager
@contextmanager
def tag(name: str):
print(f"[{name}] start")
yield
print(f"[{name}] end")
with (
tag("a"),
tag("b"),
):
print("work")
Cleaner than nested with blocks for multiple managers.
dataclass improvements#
from dataclasses import dataclass, field
@dataclass(kw_only=True, slots=True, frozen=True)
class Config:
host: str = "localhost"
port: int = 8080
tags: list[str] = field(default_factory=list)
| Flag | Version | Effect |
|---|---|---|
kw_only=True |
3.10 | All fields keyword-only |
slots=True |
3.10 | __slots__, lower memory |
frozen=True |
3.7+ | Immutable instances |
Exception groups and except* (3.11+)#
def run_tasks():
raise ExceptionGroup(
"task failures",
[
ValueError("bad input"),
TypeError("wrong type"),
],
)
try:
run_tasks()
except* ValueError as eg:
for exc in eg.exceptions:
print("value error:", exc)
except* TypeError as eg:
print("type errors:", len(eg.exceptions))
| Concept | Detail |
|---|---|
ExceptionGroup |
Bundles multiple exceptions from parallel tasks |
except* |
Handles matching sub-exceptions, re-raises rest |
BaseExceptionGroup |
Includes KeyboardInterrupt, etc. |
Relevant for asyncio.TaskGroup and structured concurrency.
Self type (3.11+)#
from typing import Self
class Builder:
def reset(self) -> Self:
self._state = {}
return self
def with_name(self, name: str) -> Self:
self._state["name"] = name
return self
Subclass return types stay correct without quotes or TypeVar boilerplate.
tomllib — read TOML from stdlib (3.11+)#
import tomllib
from pathlib import Path
config = tomllib.loads(Path("pyproject.toml").read_bytes())
# or tomllib.load(binary_file) — must be binary mode
| Module | Direction | Version |
|---|---|---|
tomllib |
Read | 3.11+ stdlib |
tomli |
Read | Backport for < 3.11 |
tomli-w |
Write | Third-party |
Improved error messages (3.11+)#
Python 3.11+ pinpoints error locations in expressions:
# SyntaxError points to the exact position in multi-line expressions
# TypeError suggestions: "Did you mean 'append'?"
3.12 adds more friendly NameError hints and f-string error locations (PEP 701 — f-strings can contain any expression including quotes).
PEP 701 f-strings (3.12+)#
Type parameter syntax (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()
def first[T](items: list[T]) -> T:
return items[0]
PEP 695 replaces many TypeVar + Generic patterns. Classic syntax still works — see Type Hints and Annotations.
type statement (3.12+)#
typing.override (3.12+)#
from typing import override
class Base:
def save(self) -> None: ...
class Derived(Base):
@override
def save(self) -> None:
...
Static checkers error if the parent method does not exist — catches rename typos.
Walrus operator := (3.8+, still essential)#
# Read in [File Handling](../../Python%20Intermediate/File%20Handling.md) patterns
if (n := len(data)) > 10:
print(f"large: {n}")
while (line := f.readline()):
process(line)
Assign and test in one expression — reduces duplication.
zoneinfo — IANA time zones (3.9+, common in modern code)#
from zoneinfo import ZoneInfo
from datetime import datetime
dt = datetime(2025, 7, 7, 12, 0, tzinfo=ZoneInfo("Asia/Kolkata"))
Prefer over pytz for new projects.
Python 3.13 highlights#
Free-threaded CPython (experimental)#
Optional python3.13t build — see Global Interpreter Lock.
Experimental JIT#
Enabled with PYTHON_JIT=1 in some builds — copy-and-patch JIT, performance varies by workload. Not a replacement for algorithmic improvements.
Improved REPL#
Multiline editing, color, better history — affects developer experience, not deployment semantics.
copy.replace() for dataclasses (3.13)#
from dataclasses import dataclass, replace # replace since 3.7
# 3.13 adds copy.replace on some immutable types in broader stdlib push
Use dataclasses.replace for immutable config updates:
Deprecated / removed awareness#
| Item | Status |
|---|---|
distutils |
Removed 3.12 — use setuptools / packaging |
imp |
Removed 3.12 — use importlib |
typing.TypedDict functional form |
Prefer class syntax |
Old % string formatting |
Still works — f-strings preferred |
Check Modules and Packages for modern packaging.
Choosing a minimum version#
| Target | Rationale |
|---|---|
| 3.10 | match, \| unions, kw_only dataclasses |
| 3.11 | Exception groups, Self, faster CPython |
| 3.12 | Type params, override, better errors |
| 3.13 | Free-threading experiments, JIT trials |
Document requires-python = ">=3.11" in pyproject.toml for new libraries.
Interview traps (quick reference)#
| Trap | What goes wrong | Safe approach |
|---|---|---|
match is switch from C |
No fall-through; different semantics | Learn pattern forms |
case [x, y] matches any 2-list |
Also matches strings (sequences!) | Know sequence patterns |
except* vs except |
Different re-raise behavior | Use except* only with groups |
tomllib.load text mode |
TypeError — needs bytes | read_bytes() or "rb" |
X \| Y at runtime without from __future__ |
Syntax error in 3.9 | Require 3.10+ |
| Free-threading is default in 3.13 | Still optional separate build | Check sys._is_gil_enabled() |
| PEP 695 requires runtime 3.12 | Syntax error on older interpreters | Match requires-python |
Mental model checklist#
- What patterns can
match/casedestructure? - When do you use
except*instead ofexcept? - What is the difference between
Union[X, Y]andX | Y? - Why must
tomllibread binary files? - What does
typing.overridecatch at check time? - What is the free-threaded build in 3.13?
What's next#
| Topic | Page |
|---|---|
| Full typing guide | Type Hints and Annotations |
| GIL / free-threading | Global Interpreter Lock |
| Error handling | Error Handling |
| Packaging | Modules and Packages |