Foundations — Context managers — with statement, `__enter__` - `__exit__`
Before you can read the parent note, you must already own a small pile of ideas: what an object is, what a method is, what those __double_underscore__ names mean, what an exception is, and what a try/finally does. The parent page uses all of these in line one. This page builds each from nothing, in an order where every idea rests only on the ones before it.
1. An object is a labelled box that carries both data and skills

Look at the figure: the orange box is one object. Inside the top compartment sit its stored values (start, elapsed). The bottom compartment lists the skills it can perform. The name t on the left is just a label pointing at the box — the box itself lives in memory, and t is an arrow to it.
2. A method is a skill that belongs to an object; self is the box itself
When you write t.start_timing(), Python rewrites it as Timer.start_timing(t) — it passes the box t in as self. That is why every method's first slot is self: so the skill knows which box's data to read and write.
3. Dunder names — the double-underscore convention
The underscores are a signal, not magic syntax. They mean: "Python's machinery is watching for this exact name." When Python sees a with statement, it looks inside your object for the names __enter__ and __exit__. If they exist, it uses them.
4. An exception is a signal that says "something went wrong, stop normal flow"

Follow the figure top to bottom. Normal execution runs line by line (the teal path). At the line that fails, a raise happens (the orange burst): control leaps out of the normal path and travels up looking for a catcher. If nothing catches it, the program crashes and prints a traceback.
An exception carries three pieces of information, and you will meet them again as __exit__'s three arguments:
5. try / except / finally — choosing what runs when things break

The figure shows the three exits from a try. Whether the body finishes cleanly (teal), or raises and is caught (orange), or raises and is not caught (plum, still propagating upward), the finally block runs on every path — it sits astride all three roads out.
6. Booleans and truthiness — why "return None" means "don't swallow"
This matters for one exact reason on the parent page:
7. The with EXPR as VAR: shape — naming the parts
Prerequisite map
Read it bottom-up: objects grow methods, methods grow dunders, dunders feed the with shape; exceptions grow the three-part TVT report and the try/finally guarantee; truthiness decides the swallow flag. All arrows converge on Context managers.
Equipment checklist
What is an object, in two words?
What does self refer to inside a method?
Why is __enter__ written with double underscores?
What three pieces of info does a raised exception carry?
Which block runs whether or not an exception occurs?
finally.Is None truthy or falsy?
If __exit__ returns None, does the exception propagate or get swallowed?
In with EXPR as VAR:, where does VAR's value come from?
__enter__, not the manager itself.Which parent-topic method is guaranteed to run because of finally?
__exit__.Connections
- Parent topic — this page is the from-zero foundation for it.
- Dunder methods — where
__enter__/__exit__come from. - Exception handling — try-except-finally — the raise/catch machinery and the
finallyguarantee. - File I/O — the canonical
with open(...)object.