Python trades raw control for speed of expression. Objects are heap-allocated and managed by reference counting backed by a cycle collector, values carry their types at runtime, and the reference interpreter runs Python bytecode behind a global lock. Its performance-critical parts, and its bridges to the rest of the system, are written in C through a stable C API, which makes Python as much a glue language over compiled code as a language in its own right. The scientific-Python and machine-learning stack, from NumPy to PyTorch, is the canonical example: a thin Python surface over compiled C, C++, and CUDA, which is much of why Python became the lingua franca of machine learning.
Python’s position in this section’s generics comparison is a third kind of erasure. Java erases for compatibility with pre-generic code, TypeScript erases because the runtime was never told about types at all, and Python keeps its annotations as live objects that no one enforces. list[int] is a real object built by a real method call at import time, and it means nothing to the interpreter. The whole generic system exists for a checker that runs before the program does, which makes the gap between what the checker proves and what the runtime does the most interesting thing in the folder.
The object model
Protocols rather than an inheritance tree. Most of the language is a consequence of these six.
- The Data Model and Dunder Methods - what
x[i]andlen(x)actually call, and why special methods are looked up on the type - The Descriptor Protocol - methods, properties,
classmethod, and__slots__as one mechanism in different clothes - Metaclasses and Class Creation - what
typedoes when a class body finishes, and the conflict rule that makes a metaclass permanent - The MRO and C3 Linearization - the merge that turns an inheritance graph into one lookup order, and the hierarchies it rejects
- Slots and Instance Layout - trading a per-instance dictionary for a fixed array, and the inheritance rules that quietly give it back
- Dataclasses and attrs-Style Classes - a decorator that reads annotations and writes methods, and the mutable-default trap
Iteration, context, and the syntax built on protocols
- Iterators vs Iterables and the Sequence Protocol - two protocols, three methods, and one legacy fallback
- Generators and Iterators in Python - what
yieldfreezes, and the real cost against the list it replaces - Comprehensions and Generator Expressions - the implicitly nested scope, and the one iterable evaluated eagerly
- Context Managers and the with Statement - the exact expansion of
with, and__exit__as an exception switch - Decorators in Python -
@as a rebinding rule, and how a decorator taking arguments is a different animal
Gradual typing, and the type parameter
- Type Hints and Gradual Typing - annotations as data the interpreter stores and never checks
- TypeVar and Generic Functions - a declaration that two positions must be filled by the same thing, and bound against constraint
- PEP 695 Type Parameter Syntax - a real lexical scope, lazily evaluated bounds, and inferred variance
- Variance in Python Generics - why
listis invariant, and the algorithm that made declaring variance unnecessary - Self and Recursive Bounds - what
Selfreaches that a hand-written recursive bound cannot
Structural typing, where Python differs most
- Protocols and Structural Subtyping - moving the interface declaration from the implementer to the consumer
- Runtime-Checkable Protocols and Their Limits -
isinstancetests for names and never signatures, and the bug lives in that gap
Describing what a plain parameter cannot
- ParamSpec and Callable Types -
Callable[..., T]means do no validation, and what replaces that hole - TypeVarTuple and Variadic Generics - a variable standing for a tuple of types, and the more instructive list of what it cannot do
- Overload and the Stub Model - a function that raises if you call it, a file that shadows the module it describes, and typeshed at ecosystem scale
Where the checker stops and the runtime begins
- Generics at Runtime and __class_getitem__ -
list[int]as a real object, and whatget_type_hintswill run for you - Type Narrowing, TypeGuard, and TypeIs - a promise about one branch against a promise about both
- Any, object, and Never - an unknown static type rather than a set of values, and a consistency relation that is not transitive
The interpreter and its edges
- CPython’s Object Model and Reference Counting - one representation choice explaining destructor timing, the cycle collector, and the difficulty of change
- The Bytecode and the Eval Loop - code objects, frames, and a specializing interpreter that rewrites instructions as it runs
- The Import System - the
sys.modulescache, the path based finder, and what happens on first import - The C API and Extension Modules - ownership rules with no compiler to check them, and an interface that became the interpreter’s hardest constraint
- Packaging, Wheels, and Environments - why an sdist install runs arbitrary code, and where the supply-chain risk moved
Concurrency and failure
- The GIL and Python Concurrency - what the lock protects, and how threads, processes, and asyncio divide the workload space
- Free Threading and the End of the GIL - reference counting rebuilt around single-thread ownership, and who pays for it
- asyncio and the Event Loop - why calling a coroutine does nothing, and what one blocking call costs every other task
- Exception Groups and Tracebacks - a linked list built during unwinding, and a structure that could only describe one failure
Read from the comparative layer
- Who Frees the Memory - CPython reference counting and the cycle collector
- The C ABI and Foreign Function Interfaces - the CPython C API,
ctypes, and calling into native code - Generics, Monomorphization vs Erasure - annotations that survive as objects but bind nothing
- Serialization and Wire Formats - the
structmodule and packing bytes for the wire
Any pages placed under this folder are auto-listed below by Quartz.