1.3.4 · D1Python Intermediate

Foundations — Context managers — with statement, `__enter__` - `__exit__`

1,770 words8 min readBack to topic

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

Figure — Context managers — with statement, `__enter__`  -  `__exit__`

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"

Figure — Context managers — with statement, `__enter__`  -  `__exit__`

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

Figure — Context managers — with statement, `__enter__`  -  `__exit__`

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

Object = data plus skills

Method and self

Dunder names auto-called

Exception = go-wrong signal

Type Value Traceback

try except finally

finally always runs

Truthy and falsy

with EXPR as VAR shape

Context managers

Files locks timers

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?
Data + skills (values + methods).
What does self refer to inside a method?
The specific object the method was called on.
Why is __enter__ written with double underscores?
It's a dunder — a hook Python calls automatically at a special moment.
What three pieces of info does a raised exception carry?
Type (kind), Value (the error object), Traceback (where it happened).
Which block runs whether or not an exception occurs?
finally.
Is None truthy or falsy?
Falsy.
If __exit__ returns None, does the exception propagate or get swallowed?
Propagates (None is falsy).
In with EXPR as VAR:, where does VAR's value come from?
The return value of __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 finally guarantee.
  • File I/O — the canonical with open(...) object.