Intermediate Syntax and Structures#
This page bridges Python Basics and advanced topics. It covers modern syntax (3.10+), extended unpacking, richer comprehensions, dataclass, Enum, and typing constructs you will see in production code and stronger take-home submissions.
How to use this page
Read after completing Basics. Focus on patterns you can use immediately in interview helpers and local tooling. Deep typing: Function Annotations and Type Hints.
At a glance
| Track | Python Intermediate |
| Sections | 11 major topics |
| Outline | Use the right-hand TOC to jump |
Topics: Extended unpacking · Structural pattern matching (match, 3.10+) · Walrus operator (:=, 3.8+) · Advanced comprehensions · dataclass — structured records (3.7+) · Enum — named constants · Typing beyond basics · Slices and sequence tricks · … (+3 more)
- Extended unpacking
- Structural pattern matching (
match, 3.10+) - Walrus operator (
:=, 3.8+) - Advanced comprehensions
dataclass— structured records (3.7+)Enum— named constants- Typing beyond basics
- Slices and sequence tricks
elseon loops andtry(intermediate nuance)- F-strings — intermediate features
- Context managers preview
Extended unpacking#
Star unpacking in assignments#
first, *middle, last = [1, 2, 3, 4, 5]
# first=1, middle=[2,3,4], last=5
a, b, *rest = range(5) # a=0, b=1, rest=[2,3,4]
# Merge iterables
combined = [*nums_a, *nums_b]
merged = {**defaults, **overrides} # dict merge; 3.9+ also: defaults | overrides
Rules:
- At most one starred target per assignment side.
- Star captures a list, not a tuple (CPython 3.x).
Unpacking in function calls and definitions#
def connect(host, port, timeout=30):
...
config = {"host": "localhost", "port": 8080}
connect(**config)
connect(*("localhost", 8080))
def log(msg, *args, **kwargs):
print(msg, args, kwargs)
Full parameter model: Functions and Scope, Parameter Unpacking.
Structural pattern matching (match, 3.10+)#
Beyond basic if/elif, match compares structure:
def handle(event: dict):
match event:
case {"type": "click", "x": x, "y": y}:
return f"click at ({x}, {y})"
case {"type": "key", "code": code}:
return f"key {code}"
case {"type": "quit"}:
return "shutdown"
case _:
raise ValueError("unknown event")
Pattern types (intermediate subset)#
| Pattern | Example | Notes |
|---|---|---|
| Literal | case 404: |
Equality match |
| Capture | case x: |
Binds value |
| Sequence | case [x, y]: |
Fixed length |
| Star | case [first, *rest]: |
Variable tail |
| Mapping | case {"id": id, **extra}: |
Required keys; extras optional |
| OR | case 401 \| 403: |
Multiple literals |
| Guard | case x if x > 0: |
Extra condition |
| Class | case Point(x=x, y=y): |
Attribute patterns |
| AS | case [x, y] as pair: |
Bind whole match |
Gotchas#
# Mapping patterns do NOT require exact key set — extra keys allowed
case {"a": 1}: # matches {"a": 1, "b": 2}
# Sequence patterns require exact length unless star used
case [x, y]: # does NOT match [1, 2, 3]
# Match uses structural rules, not duck typing inheritance
For most DSA interviews, if/elif remains default — use match when branching on shape of data (JSON events, AST nodes, command tokens).
Basics intro: Control Flow.
Walrus operator (:=, 3.8+)#
Assign and use value in one expression:
# While loop
while (line := input().strip()) != "quit":
process(line)
# Avoid double computation in comprehension
results = [y for x in data if (y := transform(x)) > threshold]
# Conditional reuse
if (match := pattern.search(text)):
print(match.group(1))
Do not use walrus when a plain assignment before the block is clearer — readability wins in interviews.
Advanced comprehensions#
Nested and filtered#
matrix = [[i * j for j in range(3)] for i in range(3)]
pairs = [(x, y) for x in nums if x > 0 for y in other if y != x]
# Dict / set
index = {v: i for i, v in enumerate(items)}
unique_lengths = {len(w) for w in words}
Dict comprehension vs defaultdict vs Counter#
| Task | Best tool |
|---|---|
| Transform keys/values once | Dict comprehension |
| Group lists by key | defaultdict(list) |
| Count frequencies | Counter |
| Incremental counting in loop | .get(k, 0) + 1 |
# WRONG for counting — O(n²)
freq = {ch: s.count(ch) for ch in set(s)}
# RIGHT
from collections import Counter
freq = Counter(s)
dataclass — structured records (3.7+)#
Reduce boilerplate for data-holding classes:
from dataclasses import dataclass, field
@dataclass
class Interval:
start: int
end: int
def __post_init__(self):
if self.start > self.end:
raise ValueError("start must be <= end")
@dataclass(order=True)
class Task:
priority: int
name: str = field(compare=False) # exclude from ordering
@dataclass(frozen=True)
class Point:
x: int
y: int
| Option | Effect |
|---|---|
frozen=True |
Immutable — hashable if fields hashable |
order=True |
Generate comparison methods |
slots=True (3.10+) |
__slots__ — lower memory, no __dict__ |
field(default_factory=list) |
Mutable default done correctly |
Compare to namedtuple and plain classes in Classes and OOP Basics.
Enum — named constants#
from enum import Enum, auto, IntEnum
class Status(Enum):
PENDING = "pending"
DONE = "done"
FAILED = "failed"
class Direction(IntEnum):
NORTH = 1
EAST = 2
SOUTH = 3
WEST = 4
Status.PENDING == "pending" # False — compare .value if needed
Status.PENDING.value == "pending" # True
Use Enum when a fixed set of named constants improves readability (HTTP codes, states in state machines). IntEnum members compare equal to integers.
Typing beyond basics#
Type hints document intent; they are not enforced at runtime without a checker (mypy, pyright).
# Python 3.9+ — built-in generics
def merge(a: list[int], b: list[int]) -> list[int]:
return sorted(a + b)
# Union and optional
def find(items: list[str], target: str) -> int | None:
...
# Callable
from collections.abc import Callable
def apply(fn: Callable[[int], int], x: int) -> int:
return fn(x)
# Literal — fixed set of values
from typing import Literal
Mode = Literal["r", "w", "a"]
def open_mode(mode: Mode) -> None: ...
# TypedDict — dict with known keys (static checking only)
from typing import TypedDict
class UserDict(TypedDict):
name: str
age: int
Runtime type check: isinstance(x, list) — not type(x) == list when subclasses matter.
Deep dive: Type Hints and Annotations.
Slices and sequence tricks#
s = "abcdef"
s[::2] # every second char
s[::-1] # reverse
s[1:None:2] # same as s[1::2]
lst = [0, 1, 2, 3, 4]
lst[2:2] = [99] # insert at index 2
del lst[1:3] # delete slice
Slice objects are reusable:
else on loops and try (intermediate nuance)#
Loop else#
Runs when loop completes without break:
try/else#
Runs when try block completes without exception:
Details: Error Handling.
F-strings — intermediate features#
x = 42
f"{x=}" # "x=42" debug syntax (3.8+)
f"{x:_>10}" # alignment and fill
f"{pi:.2f}"
f"{n/b:.1%}" # percentage
f"{dt:%Y-%m-%d}" # datetime format
# Expressions and calls
f"{len(items)} items"
f"{obj.method()}"
Prefer f-strings over % and .format() in new code — see Strings.
Context managers preview#
from contextlib import contextmanager
@contextmanager
def timer(label: str):
start = time.perf_counter()
try:
yield
finally:
elapsed = time.perf_counter() - start
print(f"{label}: {elapsed:.3f}s")
with timer("sort"):
data.sort()
File and resource patterns: File Handling.
Interview traps (quick reference)#
| Trap | What goes wrong | Safe approach |
|---|---|---|
| Star assignment twice | SyntaxError | One * target per side |
match mapping exact keys |
Extra keys still match | Read pattern spec |
Enum vs string compare |
Always False | Use .value or compare to Enum member |
| Nested comprehension unreadable | Bugs in interviews | Use regular loop |
| TypedDict at runtime | No validation | Treat as plain dict |
| Walrus in unclear spots | Hard to read | Assign on previous line |
Mental model checklist#
- How does
{**a, **b}differ froma \| b(3.9+)? - When is
matchbetter thanif/elif? - Why use
@dataclass(frozen=True)? - What does loop
elsemean — when does it run? - Are type hints enforced at runtime by default?
What's next#
| Topic | Page |
|---|---|
| Scope and closures | Functions and Scope |
| OOP patterns | Classes and OOP Basics |
| Stdlib data tools | Data Handling and Standard Library |
| Advanced typing | Type Hints and Annotations |