Concepts / Understanding Function Scope

Understanding Function Scope

A useful way to reason about scope is to attach each variable name to the block in which it is declared.

  • Programming
Interactive lab

Try it: Scope: Local, Enclosing, Global, Built-in

How Python looks up a name Local → Enclosing → Global → Built-in, why assigning to a name inside a function makes it local (and raises UnboundLocalError if it is read first), and what global, nonlocal and closures change.

How it works

  1. Before a function runs, Python marks every name assigned inside it as local to that function, unless it is declared global or nonlocal.
  2. Reading a name searches the local namespace, then enclosing functions, then the module's globals, then the built-ins; the first hit wins.
  3. A local name read before it has a value raises UnboundLocalError (Python does not fall back to the global).
  4. global x makes assignments go to the module namespace; nonlocal x makes them go to the nearest enclosing function.
  5. A function's local frame disappears when it returns, unless an inner function (a closure) still uses its variables.

Default run (10 steps): Ready: Local shadows global. Every name is looked up Local, then Enclosing, then Global, then Built-in. … Finished. Printed: inside: 99 / outside: 10.

Simplified: The lab's own small Python interpreter runs a fixed, hand-written script (you choose the variant and the values, never the code); nothing is executed as real Python. Every script was run in CPython 3.12 with the same inputs and the lab reproduces its output and error messages. Built-ins shows only the names the script used.

Educational simulation

Loading the simulation…

Two Names, Two Variables

Imagine that a program has a variable named x outside a function. The function also declares a variable named x. These names look identical, but the two variables are not related. The x declared inside the function belongs to the function's local scope, while the other x belongs to the surrounding scope. Changing one does not make the two variables become the same variable.

outer xvalue 10function xvalue 20
Which x does the function use, and do the two variables affect each other?

Tracing the Function Boundary

Worked example

Following Two Variables Named score

An outside part of a program has score with the value 50. A function declares its own score with the value 80. What happens to each variable?

  1. 1
    Outside declaration

    The outside score belongs to the scope of the block where it was declared.

  2. 2
    Function declaration

    The function's score belongs to the function's local scope. It is not related to the outside score, even though the name is the same.

  3. 3
    Separate changes

    A change to the function's score concerns the function-local variable. It does not turn that variable into the outside score.

Result

The two score variables are separate because each name is local to its own scope.

A useful way to reason about scope is to attach each variable name to the block in which it is declared. A function definition creates a boundary for names declared inside it. The same spelling can appear outside that boundary without referring to the function's local variable. Scope therefore describes where a declared name belongs, not merely how the name is written.

What the Scope Boundary Contains

top-level blockoutside functionfunction blockfunction scopelocal variable namedeclared in functioncontainsdeclares
Which block contains a variable name, and where does a function-local name belong?
Definition

The scope of a variable is the block in which its name is declared, beginning at the point where that name is defined. For a variable declared inside a function definition, that block is the function's local scope.

The function boundary prevents an inside declaration from becoming related to an outside declaration with the same name. This is why a function can use a local name without making that name the same variable as one used elsewhere in the program.

When a Name Becomes Available

before definitionname not yet definedx definitionscope beginsafter definitionname in its blockreachescontinues
What changes before and after a variable declaration inside a block?

Scope does not begin at an arbitrary place in the block. The rule is tied to the point where the variable name is defined. Before that point, the name has not yet begun its scope in that block. From the definition point onward, the name has the scope of that block.

Worked example

Locating the Start of Scope

A block contains several statements, and the name total is defined partway through the block. Identify where total begins to have scope.

  1. 1
    Before the definition

    The name total has not yet been defined at this point in the block.

  2. 2
    At the definition

    This is the point at which the name total is introduced.

  3. 3
    After the definition

    The name total has the scope of the block from this point onward.

Result

The scope of total begins at its point of definition and continues within its declared block.

Assigning to a Top-Level Name

This rule is about assignment to a top-level name from inside a function. It does not erase the distinction between the function's local scope and the top-level scope. Instead, the global statement tells Python that the assignment is intended for the top-level name rather than for a local name.

Mistakes Beginners Make

  • Common mistake

    Assuming that identical names refer to one shared variable.

    What it looks like

    An outside variable named count and a function-local variable named count are treated as if they were automatically connected.

    Why it fails

    Variables declared inside a function are not related to variables with the same names outside the function.

    Do this instead

    Track each name together with the block where it was declared.

  • Common mistake

    Treating scope as if it starts everywhere in the block at once.

    What it looks like

    A variable is assumed to have scope before its declaration point.

    Why it fails

    The scope of a variable begins from the point where its name is defined.

    Do this instead

    Mark the definition point first, then treat the name as belonging to its block from that point onward.

  • Common mistake

    Assigning to a top-level name inside a function without using global.

    What it looks like

    A function attempts to assign a value to a name defined at the top level but does not use the global statement.

    Why it fails

    The source rule states that assignment to a variable defined outside a function is impossible without the global statement.

    Do this instead

    Use the global statement when the intended assignment is to a top-level name.

Practice the Trace

EASY

A program has an outside variable named level. A function declares another variable named level. Write a short explanation that identifies the scope of each name and explains whether the two variables are related. Then state the point at which the function-local level begins to have scope.

Hints
  • Name the block where each level is declared.
  • Remember that identical names do not make variables related across function boundaries.
  • Use the definition point to identify when the local name begins its scope.

Key Takeaways

  1. 1
    A variable's scope is the block where its name is declared.
  2. 2
    A variable declared inside a function is local to that function.
  3. 3
    An inside variable and an outside variable can share a name without being related.
  4. 4
    Scope begins at the point where the variable name is defined.
  5. 5
    The global statement is required when a function assigns to a name defined at the top level.

At a glance

  • Function scope keeps names declared inside a function separate from same-named variables outside it.
  • The block of declaration determines a variable's scope.
  • A variable's scope begins at its definition point.
  • Use the global statement when a function must assign to a top-level name.

Related concepts

More concepts starting with U