Scope

Local vs global names, and why not to mutate globals.

A name assigned inside a function is local. A name assigned at the top of a cell is global for that interpreter (it survives into the next cell until reload).

Goal

See local names hide globals, and avoid writing global unless you must.

Local hides global

city = "Nairobi"

def report():
    city = "Mombasa"
    print("inside:", city)

report()
print("outside:", city)

The function’s city is a different name. The outer city is unchanged.

Read globals

rate = 0.16

def with_tax(amount):
    return amount * (1 + rate)

print(with_tax(100))

Reading a global is fine. Assigning to it without global creates a local instead.

Assignment makes a local

count = 0

def bump():
    # count += 1  # UnboundLocalError — uncomment to see it
    return count

print(bump())
count = 0

def bump():
    global count
    count += 1

bump()
bump()
print(count)

Prefer returning a new value over global:

def bump(count):
    return count + 1

n = 0
n = bump(n)
n = bump(n)
print(n)
Pitfall

global makes tests and reuse harder. Pass arguments in, return results out.