Skip to main content
🧠

Senior Deep-Dives

L5PRO· 161 lessons

asyncio internals, GIL, typing tricks, Rust extensions

0 / 161 · 0%

161 lessons across 6 modules: concurrency & async internals, CPython internals & performance, metaclasses + descriptors + dunder magic, memory + profiling + optimization (memray/tracemalloc), and architecture + code review + senior judgment.

Before you start

  • ·2+ years of Python in production. You've shipped something that failed at 2am
  • ·Comfortable with type hints, dataclasses, async/await. We go into asyncio internals — not basics
  • ·You've read profiler output once and felt confused. Good — that's what we fix

After you finish

ℹ️ Heads-up on the format: Senior Deep-Dives are mostly concept lessons + code reviews + predict-the-output exercises. Some samples touch CPython internals or C-extension boundaries that Skulpt/Pyodide can't execute — those run as walkthroughs, not live-runnable code.

0/483 stars· 0% complete

Resume →

Prerequisites — what you should know before this track

The GIL — what it is, what it isn't

FREE

asyncio: event loop deep-dive

Typing: TypeVar, Generic, Protocol

Metaclasses

Descriptors

Memory and reference counting

Profiling: cProfile, py-spy, memory_profiler

concurrent.futures vs asyncio vs threading

Rust extensions via PyO3

Packaging modern Python apps

Testing strategies at scale

Observability: metrics, traces, logs

Production debugging

API design — pagination, errors, versioning

Capstone: redesign a hot path

The dis module — reading Python bytecode

Slots optimization in depth

Weak references (weakref module)

functools.singledispatch — type-dispatch

contextlib.contextmanager

🎯 Review: Senior Python module 1 recap

ExitStack for dynamic context management

asyncio.TaskGroup (Python 3.11+) vs gather

Cancellation patterns in asyncio

asyncio.Semaphore for backpressure

trio vs asyncio — when to pick which

Cython basics — typing hot paths

mypy strict mode + custom plugins

ParamSpec and Concatenate (typing 3.10+)

Generic protocols (typing.Protocol with TypeVar)

Memory views and buffer protocol

struct module for binary parsing

logging filters and adapters

Building custom pytest plugins

Debugging deadlocks (py-spy + gdb)

Capstone: profile + optimize a real bottleneck (CPU + memory)

CPython internals: bytecode and frame objects

PEP 703: no-GIL Python — what changes

Faster CPython: 3.11 / 3.12 / 3.13 improvements

Sub-interpreters (PEP 684, PEP 734)

asyncio internals: event loop step-by-step

🎯 Review: Senior Python module 2 recap

uvloop vs default asyncio loop

Trio's structured concurrency principles

Multiprocessing pitfalls: pickle, fork vs spawn

NumPy vectorization patterns

Numba JIT for hot Python loops

PEP 695: Type Parameters syntax (Python 3.12)

Variadic generics: TypeVarTuple and Unpack

typing.Self and @override (3.11+)

dataclass slots and kw_only

attrs vs dataclass vs Pydantic — when each wins

msgspec for ultra-fast (de)serialization

pydantic_settings for typed env config

Logging at scale: structlog + sampling + sinks

Open Source contribution flow

Capstone: redesign a slow Python service end-to-end

Cython basics — when pure Python isn't enough

C extensions via ctypes / cffi

PyO3 — Rust extensions for modern Python

AST manipulation with the `ast` module

Predict: bytecode introspection with `dis`

🎯 Review: Senior Python module 3 recap

Coroutine internals — `__await__` from scratch

asyncio TaskGroups + ExceptionGroup (3.11+)

Subinterpreters + free-threading (PEP 684, 703)

Memory views and the buffer protocol

__slots__ deep dive

Weak references and finalizers

GC tuning — generations and freeze

Profilers: cProfile vs pyinstrument vs py-spy

Memory profiling: tracemalloc + memray

Bytecode caching — __pycache__ internals

Import system internals — finders and loaders

Pattern matching internals — __match_args__

Type system: ParamSpec, TypeVarTuple, Self

Protocols vs ABCs vs duck typing

🏆 Capstone — diagnose a memory leak in production

When to introduce an abstraction

Code review: nitpicks vs blockers

Refactoring: characterization tests first

API design: stability vs ergonomics

Naming: domain language wins

🎯 Review: Senior Python module 4 recap

Error handling: exceptions vs Result types

Logging vs metrics vs tracing

Migrations: expand → migrate → contract

Concurrency: actor model vs shared memory

Mocking: when it lies to you

Documentation: ADRs for irreversible decisions

Testing pyramid: unit > integration > e2e

Logging PII: regulatory implications

Caching: cache-aside vs read-through

Threading: futures vs raw threads

Generators: yield from + send

Pickling: security warning

Memory leaks: cycles and weakref

Architecture: monolith vs microservices

Senior interview signal: 'show me the postmortem'

On-call: runbook is the contract

Senior glue work: invisible but irreplaceable

Tech debt: pay down with feature work

Mentoring: review with questions, not answers

🏆 Final senior capstone: judgment under uncertainty

Descriptor lookup order — data vs non-data

C3 linearisation — predict the MRO

contextvars in async — Task context isolation

typing.Protocol — runtime_checkable's hidden hole

asyncio reentrance — you can't nest `asyncio.run()`

functools.cache — hashability is the gate

Walrus in comprehensions — scope leak gotcha

functools.partial vs lambda — closure timing

dataclass field(default_factory) — the mutable-default block

Sentinel object — distinguishing 'not passed' from 'passed None'

__init_subclass__ — auto-registration without metaclasses

enum.IntFlag — bitwise composition and the `in` operator

WeakValueDictionary — caches that let GC do its job

`__slots__` — when you're paying for `__dict__` you don't use

contextlib.ExitStack — dynamic context-manager composition

functools.singledispatch — type-dispatched generic functions

@dataclass(frozen=True) + dataclasses.replace — immutable updates

@runtime_checkable Protocol — structural typing + its blind spots

__match_args__ — making your classes destructurable

🏆 Module 7 capstone: composing the seven patterns into a real design

asyncio.Semaphore — bounded concurrency without blocking the loop

asyncio.shield — let the inner work finish even when the outer awaiter walks away

asyncio.as_completed — stream results as tasks finish

asyncio.Queue — bounded backpressure between producer and consumer

asyncio.Lock — FIFO-fair, NOT reentrant, cancellation-safe

asyncio.Event — one-shot broadcast that stays set

asyncio.TaskGroup — structured concurrency (3.11+) replaces gather

🏆 Module 8 capstone: async correctness in a real ingest pipeline

Custom exception hierarchies — most-specific except first

Mis-ordered except clauses — when subclass handlers become dead code

Exception chaining: `raise X from Y` vs implicit context vs bare re-raise

contextlib.suppress — quietly skip specific exceptions

traceback.TracebackException — exceptions as data

ExceptionGroup + except* — multiple failures, one raise

Retry decorator — bounded attempts + exponential backoff + targeted catch

🏆 Module 9 capstone: batch CSV importer with structured error handling

pathlib.Path — the modern alternative to os.path string-pushing

@dataclass(kw_only=True, slots=True) — the modern senior default

typing.Annotated — metadata that hides BEHIND the type

enum.StrEnum — type-safe strings that serialise like strings

typing.Self (3.11+) — fluent builders that subclass correctly

typing.Never + assert_never — exhaustiveness checks the compiler enforces

TypedDict + NotRequired — JSON shapes as types

🏆 Module 10 capstone: typed config-driven API client

Parametrised decorators — three nested functions, not two

Decorator stacking — TOP wraps last, runs first

Class-based decorators — when the wrapper needs state

functools.singledispatchmethod — type dispatch when there's a self in the way

@contextlib.contextmanager — context managers from generators

Descriptor protocol — the mechanic under @property and ORM columns

typing.ParamSpec — decorators that preserve the wrapped signature

🏆 Module 11 capstone: designing a published decorator library

Write: implement freeze() — a recursive hashable-converter for cache keys

Write: merge_dicts() with conflict-resolution strategies

Write: chunked() — yield successive batches from a sequence

Write: unique_by() — order-preserving deduplication with a key function

Tip: click any lesson to revisit it. After your first attempt, the “Show example” button reveals the full solution.