By Long Nguyen | Dec 5th, 2025

Python feels effortless when you’re writing it.

But CPython — the implementation most of us run — doesn’t execute “Python” so much as it executes a carefully engineered model of execution: a C interpreter driving heap-allocated frame objects, names resolved through layered namespaces, objects kept alive by reference counts, and modules treated as cached, mutable singletons. Through this model, a collection of seemingly unrelated behaviors become the same story told at different scales.

This post is a tour of that mental model after what I learned after being curious about the below

del + __del__

…and what prints in this snippet

# fiz.py
a = 10

# bar.py
import fiz
def p():
    print(fiz.a, end="")

# foo.py
import bar
import fiz

bar.p()
fiz.a = 42
bar.p()

📚 1. Two Layers: CPython’s Stack vs Python Heap


🦴 2. No “Primitives”: everything Is an Object


🔒 3. del Is Name Deletion, Not Object Deletion


🏠 4. If Variables Are “Just Names”… Where Do Those Names Live?


⚡ 5. locals() vs globals()