Skip to content
DoingCamp CS

Make it comfy

Lesson style

Quick mode shows the key picture, a summary and the practice. Good for a refresher.

Theme
Font

Both fonts are designed to be easy to read. Some readers with dyslexia prefer Lexend.

Text size
Spacing
Animations

Lesson 3 of 20 · about 15 min

Environments: where names live

Every name lookup follows a chain of frames, starting where the code is running and moving outward. This environment model explains scope, closures and nonlocal precisely.

🧭 What you need first: Functions that make functions , Scope and the call stack

The story

You’re at work and someone asks “where’s the stapler?” You check your desk first. Not there? You check your team’s shelf. Then the office supply room. Then, as a last resort, you buy one from the store. The first place you find it wins.

Python looks up names exactly like that. It searches a chain of places, called frames, from the most local outward, and uses the first match. That chain is the environment.

The surprising part, and the key to closures: a function’s chain leads to where it was written, not to where it happens to be called. A stapler request from the marketing team always checks the marketing shelf, even if the person asking is visiting the finance floor.

Another way: nicknames in families

In your house, “Mom” means your mom. At a friend’s house, “Mom” means theirs. The same name refers to different people depending on which household (frame) you’re in. When a name isn’t used in your household, you fall back to what the wider world calls it.

Play with it

Follow the lookups

Step through. When inner runs, it finds y in its own frame, x in outer’s frame, and z in the global frame. Edit the code: add a local x = 100 inside inner and see which x wins.

Watch the code run, one step at a time

  1. 1z = 1
  2. 2
  3. 3def outer(x):
  4. 4 def inner(y):
  5. 5 return x + y + z
  6. 6 return inner(10)
  7. 7
  8. 8print(outer(5))

➜ yellow = the line about to run · ✓ = the line that just ran

Name it

The real words

  • An environment is a sequence of frames. Each frame maps names to values and has a parent frame.
  • Calling a function creates a new frame whose parent is the frame where the function was defined. This rule is called lexical scope (or static scope): you can tell which names a function sees just by reading where it’s written.
  • Looking up a name: check the current frame; if it’s not there, check its parent; and so on to the global frame, then Python’s built-ins (print, len…). If no frame has it: NameError. The short version is LEGB: Local, Enclosing, Global, Built-in.
  • Assigning to a name inside a function creates or updates it in the local frame, even if an outer frame has the same name.
  • nonlocal x says “when I assign to x, update the x in the enclosing function’s frame.” global x does the same for the global frame. Both are signs of mutable state, which lesson 12 explores.
  • Shadowing: a local name hides an outer name with the same spelling. Legal, but often confusing.

This “environment model” is precisely how Python (and most languages) actually work. In F24 you’ll build an interpreter that implements it.

Build it

A counter with memory

make_counter() should return a function. Each time that function is called, it returns the next number: 1, 2, 3… Each counter keeps its own count. You'll need nonlocal.

Challenge

Defined vs called

x = 'global'. def show(): return x. def caller(): x = 'local'; return show(). What does caller() return?

Remember it

When a function is called, what is the parent of its new frame?

Got it?

Finish the lesson to color it in on your map and collect its concept cards.

Did this lesson click?