█
LastWrite
  • > Curriculum
  • > Pricing
  • > For Educators
  • > About
  • > Contact
Log InGet Started

Questions, concerns, bug reports, or suggestions? We read every message, write to us at [email protected].

More ways to reach us →
LastWrite

Structured computer science lessons for aspiring developers and security professionals.

[email protected]

(201) 785-7951

Mon–Fri, 9 AM–5 PM EST

Learn

  • Curriculum
  • Pricing

Company

  • About
  • For Educators & Schools
  • Contact Us

Legal

  • Terms of Service
  • Privacy Policy
© 2026 LastWrite. All rights reserved.
Curriculum/Programming Languages/Python (Professional)/Pythonic Code
45 minIntermediate

Pythonic Code

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.

Prerequisites:Object-Oriented Python

Comprehensions + generators

Replace most for-loops in Python.

python
# List comprehension
squares = [x*x for x in range(10)]
# Filter
evens = [x for x in range(20) if x % 2 == 0]
# Dict comprehension
name_to_age = {u.name: u.age for u in users}
# Set comprehension
tags = {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 function
def 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)

Context managers + decorators

Two of Python's killer features.

python
# 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
@contextmanager
def timer(label):
import time
start = time.time()
yield
print(f"{label}: {time.time()-start:.3f}s")
with timer("big op"):
do_work()
# Decorator (functions that wrap functions)
from functools import wraps
def logged(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
print(f"calling {fn.__name__}")
return fn(*args, **kwargs)
return wrapper
@logged
def add(a, b): return a + b

Type hints + mypy

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.

Common mistakes only experienced Python devs avoid

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.

Quick Check

When use a generator over a list?

Pick the senior answer.

Sign in and purchase access to unlock this lesson.

Sign in to purchase
←Object-Oriented Python
Back to Python (Professional)
Error Handling and Logging→