Grade by Grade
A. Programming Concepts and Skills · Arrays and Subprograms

Variable Scope: Local and Global

A3.2 A4.2 A4.1About 65 minutes
Learning goals
  • I can tell whether a variable is local or global, and where in a program it can be used.
  • I can predict the output when a local variable has the same name as a global one.
  • I can explain the UnboundLocalError and fix it, preferably with parameters and return values instead of global.
  • I can follow the convention of global CONSTANTS in capitals and keeping other data local.

Words to know

scope
The part of a program where a variable name can be used.
local variable
A variable created inside a function (including its parameters). It can only be used inside that function and disappears when the function returns.
global variable
A variable created at the top level of a file, outside every function. Any function can read it.
lifetime
How long a variable exists while the program runs. A local variable lives only during one call.
shadowing
When a local variable has the same name as a global one, so the global is hidden inside that function.
global (keyword)
A statement inside a function, e.g. global count, that makes assignments to that name change the global variable.
constant
A value that should not change while the program runs. By convention its name is in CAPITALS, e.g. TAX_RATE.

What happens in a function stays in a function

Two students on a group project both write a function, and both use a variable called total. Will they overwrite each other's totals? No, and that is one of the best things about functions. Each function has its own private set of variable names, called its local scope. The curriculum asks you to write subprograms that use appropriate variable scope (local, global). This lesson explains exactly what that means and why good programmers keep almost everything local.

Local variables

A variable is local to a function if it is created inside the function: by an assignment in the body, or as a parameter.

  • It can only be used inside that function. Using it outside gives NameError.
  • It is created fresh on each call and destroyed when the function returns. This is its lifetime.
  • Two functions can each have a local variable with the same name; they are completely separate.

Global variables

A variable created at the top level of the file (not inside any function) is global. It exists for the whole run, and any function can read it.

global scope (the whole file)TAX_RATE = 0.13cart = [4.99, 12.50, 3.25]local scope of subtotal(prices)prices (parameter)totalpcan read TAX_RATElocal scope of with_tax(amount)amount (parameter)total (a different total!)cannot see subtotal's p
Scopes nest like boxes. Code inside a function can read names in its own box and in the global box around it, but not names in another function's box. Both functions have a local called total; they never interfere.
TAX_RATE = 0.13 # global constant (HST in Ontario)
def subtotal(prices):
total = 0 # local to subtotal
for p in prices:
total += p
return total
def with_tax(amount):
total = amount * (1 + TAX_RATE) # a different local total
return round(total, 2)
cart = [4.99, 12.50, 3.25]
s = subtotal(cart)
print(round(s, 2))
print(with_tax(s))

Output: 20.74 and 23.44. subtotal and with_tax each have their own total. with_tax reads the global constant TAX_RATE (13% HST, Ontario's sales tax rate on most items). Notice that the global variable s has nothing to do with any local variable. (round(s, 2) is there because adding floats such as 4.99 can leave a tiny binary error: the unrounded sum prints as 20.740000000000002.)

timelocal total existscall startsreturnglobal TAX_RATE exists for the whole runtotal gone
The lifetime of a local variable. total inside subtotal is created when the call starts and disappears at return. The next call makes a brand-new total starting from 0.

Same name, different variable: shadowing

If a function assigns to a name, Python treats that name as local for the whole function, even if a global with the same name exists. The local shadows (hides) the global inside the function.

x = 10
def show():
x = 99 # a NEW local x; the global x is untouched
print("inside:", x)
show()
print("outside:", x)

Output: inside: 99 and outside: 10. Assigning x = 99 inside show created a local x. The global x was never touched.

The UnboundLocalError

Because of that rule, this common mistake fails:

count = 0 at the top, then a function whose body is count += 1.

The function assigns to count, so count is local in the whole function. But count += 1 needs the old value of the local count, and it does not have one yet. Python 3.13 reports:

UnboundLocalError: cannot access local variable 'count' where it is not associated with a value

(older versions say local variable 'count' referenced before assignment). There are two fixes.

count = 0
def add_visitor():
global count # use the global count, don't make a local one
count += 1
add_visitor()
add_visitor()
print(count)

Fix 1: the global statement. Output: 2. It works, but now the function silently changes data outside itself.

def add_visitor(count):
return count + 1
count = 0
count = add_visitor(count)
count = add_visitor(count)
print(count)

Fix 2 (usually better): pass the value in as a parameter and return the new value. Output: 2. The function now depends only on its parameters, so you can test it on its own: add_visitor(41) must return 42.

Professional conventions for scope

  • Keep variables local whenever you can. Data goes in through parameters and comes out through return.
  • Global constants are fine and common. Write them in CAPITALS at the top of the file: TAX_RATE = 0.13, MAX_PLAYERS = 20. Capitals tell readers "do not change this".
  • Avoid global for ordinary data. When many functions can change the same global variable, a bug in one shows up in another, and tracing becomes very hard.
  • Use different, meaningful names even when shadowing is allowed. It makes tracing easier.
Worked example

Example 1: Trace the scopes

Predict the output.

n = 5

def f(n):

    n = n * 2

    return n

def g():

    return n + 1

print(f(3), g(), n)

  1. f(3): the parameter n is local to f, so it starts at 3, becomes 6, and 6 is returned. The global n is still 5.
  2. g(): g has no local n (it never assigns n), so it reads the global n = 5 and returns 6.
  3. The last value printed is the global n, which is still 5.

6 6 5

Worked example

Example 2: Fix the NameError

This program crashes with NameError: name 'average' is not defined. Explain and fix it.

def find_average(values):

    average = sum(values) / len(values)

find_average([70, 80, 90])

print(average)

  1. average is local to find_average. When the function returns, it disappears, and the global scope never had a variable called average.
  2. The fix is not global. Return the value and store it in the caller:
  3. def find_average(values):     return sum(values) / len(values) average = find_average([70, 80, 90]) print(average)

It prints 80.0. A function's results should leave through return.

Just for fun

Local variables are like what happens at a sleepover: it exists only for that night, nobody outside ever sees it, and by morning it's all gone. (Global variables are the house rules on the fridge.)

Hands-on activity

Scope with sticky notes

You need: 3 sheets of paper, sticky notes in two colours if possible, a pen, and a computer with Python.

  1. Label one big sheet GLOBAL and two smaller sheets f and g. Put the small sheets on top of the big one, like the scope diagram.
  2. Take the program from Example 1. Each time a variable is created, write it on a sticky note with its value and stick it on the sheet for its scope. When a function returns, peel off all the notes on its sheet: their lifetime is over.
  3. When code needs a name, look on the current sheet first, then on GLOBAL.
  4. Now write your own short program that includes a shadowed name, and challenge a family member to predict the output with the sheets before you run it.

What to look for: notes for parameters go on the function's sheet, and the student removes them at return.

Your turn

1

Is a function's parameter local or global?

2

Predict the output:

def f():

    y = 3

    return y

f()

print(y)

3

Predict the output:

a = 1

def f():

    a = 2

    return a

print(f(), a)

4

Predict the output:

RATE = 3

def cost(n):

    return n * RATE

print(cost(4))

5

Why does this crash? total = 0 then def add(x): total += x.

6

Rewrite add from the last question without using global.

7

Why are constants written in capitals?

More practice: warm-up

1

Where is a global variable created?

2

When is a local variable destroyed?

3

Can two different functions both have a local variable called i?

4

Which keyword lets a function assign to a global variable?

5

Name one global constant you might use in a program about Ontario sales tax.

More practice: on your own

1

Predict the output:

x = 5

def double():

    return x * 2

x = 7

print(double())

2

Predict the output:

def f(a):

    a = a + 1

    b = a * 2

    return b

a = 10

b = f(a)

print(a, b)

3

A program uses a global list scores and a function def add_score(s): scores.append(s). It works, with no global statement. Why?

4

List two reasons why using many global variables makes a program hard to debug.

5

Predict the output:

total = 100

def spend(amount):

    global total

    total = total - amount

spend(30)

spend(25)

print(total)

Challenge

1

Predict the output and explain each value:

x = 1

def outer():

    x = 2

    def inner():

        return x * 10

    return inner() + x

print(outer(), x)

2

Refactor this program so it uses no global variables except constants, then explain how it is easier to test.

marks = [70, 85, 92]

best = 0

def find_best():

    global best

    for m in marks:

        if m > best:

            best = m

find_best()

print(best)

3

A loop variable in Python keeps its last value after the loop ends: after for i in range(3): pass, i is 2. Is i local or global if this loop is written at the top level of a file? Inside a function?

Check your understanding

Quiz

1.

Where can a local variable be used?

2.

What does this print? x = 1, def f(): x = 5, f(), print(x)

3.

Which error do you get from count = 0 and def inc(): count += 1 when inc() is called?

4.

Which is usually the best way for a function to give a result to the rest of the program?

5.

Which name follows the convention for a global constant?

6.

A function can read a global variable without the global keyword. When does it need global?

For parents and teachers

Big idea: A3.2 asks for subprograms with appropriate variable scope (e.g., local, global). "Appropriate" means: keep data local, pass it through parameters and return values, and limit globals mostly to constants. A4.2 (professional conventions) appears as CAPITALS for constants; A4.1 as fixing NameError and UnboundLocalError.

How to help: The sticky-note activity is a very effective way to see lifetimes. Ask your teen, "Where does this variable live? When does it disappear?" for each variable in a short program.

Common difficulties:

  • Expecting a variable created in a function to exist after the call (NameError).
  • Using global as a quick fix for every scope error. It hides the real problem: the value should have been returned.
  • Not realizing that assignment anywhere in a function makes the name local for the whole function.
  • Confusing "changing a global list's contents" (allowed without global) with "assigning a new value to the name" (needs global).