After this lesson, you will be able to: Write Pythonic code: comprehensions, generators, context managers, decorators, and type hints.
These are what make code 'Pythonic'. Reviewers spot them; juniors miss them.
Replace most for-loops in Python.
# List comprehensionsquares = [x*x for x in range(10)]# Filterevens = [x for x in range(20) if x % 2 == 0]# Dict comprehensionname_to_age = {u.name: u.age for u in users}# Set comprehensiontags = {t for u in users for t in u.tags}# Generator (lazy, memory-friendly for big sequences)squares_gen = (x*x for x in range(10**9)) # doesn't allocate a billion ints# Generator functiondef chunks(seq, n):for i in range(0, len(seq), n):yield seq[i:i+n]for chunk in chunks(list(range(100)), 10):print(chunk)
Two of Python's killer features.
# Context manager (always closes resources)with open("file.txt") as f:data = f.read()# f is closed even on exception# Custom context manager (the @contextmanager decorator)from contextlib import contextmanager@contextmanagerdef timer(label):import timestart = time.time()yieldprint(f"{label}: {time.time()-start:.3f}s")with timer("big op"):do_work()# Decorator (functions that wrap functions)from functools import wrapsdef logged(fn):@wraps(fn)def wrapper(*args, **kwargs):print(f"calling {fn.__name__}")return fn(*args, **kwargs)return wrapper@loggeddef add(a, b): return a + b
Annotate function signatures. Run `mypy` to catch mismatches at lint time. `from typing import Optional, Union` (or `int | None` in 3.10+). Use protocols for structural typing (duck-typed interfaces). Modern projects: ruff for fast linting + mypy or pyright for types.
Writing nested for-loops where a comprehension reads more clearly. Building lists when you only iterate once, use a generator. Forgetting `@wraps` on decorators (loses function name + docstring). Try/finally where `with` is cleaner.
Pick the senior answer.
Sign in and purchase access to unlock this lesson.