Part 4 · 1 chapters · ~8 min
Idioms
Writing Pythonic code: EAFP versus LBYL, iteration protocols, comprehensions and generator expressions, unpacking, enumerate and zip, context managers, dataclasses, pathlib, f-strings, the standard library before dependencies, and the Zen of Python in practice.
8
Pythonic code
code
# EAFP: easier to ask forgiveness than permission
try: acct = accounts[account_id]
except KeyError: raise AccountNotFound(account_id) from None
# iterate directly; enumerate and zip instead of indices
for i, (t, fee) in enumerate(zip(transfers, fees), start=1): print(f"{i}. {t.id} fee {fee}")
# unpacking and the walrus operator
first, *rest = sorted(transfers, key=lambda t: t.created_at)
if (n := len(rest)) > 100: log.warning("%d transfers pending", n)
from pathlib import Path
for p in Path("statements").glob("2026-09-*.csv"): process(p.read_text(encoding="utf-8"))
from collections import Counter, defaultdict
by_status = Counter(t.status for t in transfers) # {'completed': 812, 'pending': 41}
by_owner = defaultdict(list)
for t in transfers: by_owner[t.owner].append(t)| Pythonic | instead of |
|---|---|
if not items: | if len(items) == 0: |
with open(...) as f: | manual open/close |
dataclass or NamedTuple | dicts with fixed keys everywhere |
any(), all(), sum() with generators | accumulating loops |
| small modules with clear names | utils.py holding everything |