Local and global variables

Scope: where a variable exists, and why passing values beats global.

F4.3Functions and structured codeGCSE15 min

Do this lesson in the simulator

A variable made inside a function is not the same as one made outside it, even when they have the same name. Where a variable can be used is called its scope. Getting scope wrong gives some of the most confusing errors in Python; getting it right is what lets functions be written and tested one at a time.

Local variables stay inside

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

def measure():
    gap = distance()
    print("inside, gap is", gap)

measure()
print(gap)

Run this in the simulator

NameError on the last line. gap is a local variable: it is created when measure runs and it disappears when measure returns. The main program never had a gap. If the outside needs the value, the function should return it.

Same name, different variables

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

speed = 80

def gentle_drive():
    speed = 30
    print("inside the function, speed is", speed)
    forward(speed, distance=15)

gentle_drive()
print("outside, speed is still", speed)

Run this in the simulator

The speed = 30 inside the function made a new local variable that happened to share the name. The speed outside, a global variable because it was made in the main program, was never touched. This is a feature, not a bug: whoever writes gentle_drive does not need to know every variable name in the rest of the program.

Reading a global works; changing it does not

A function can read a global variable, but assigning to that name inside a function makes a local one instead. Run this:

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

beeps = 0

def beep():
    tone(880, 0.1)
    beeps = beeps + 1

beep()
print("beeps:", beeps)

Run this in the simulator

UnboundLocalError. Because the function assigns to beeps, Python treats beeps as local everywhere in that function, so beeps + 1 tries to read a local variable that has no value yet. There are two ways to fix it.

Fix 1: pass it in and return it

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

def beep(count):
    tone(880, 0.1)
    wait(0.1)
    return count + 1

beeps = 0
beeps = beep(beeps)
beeps = beep(beeps)
print("beeps:", beeps)

Run this in the simulator

The function takes the count as a parameter and returns the new count. Everything it uses comes in through its parameters, and everything it produces goes out through return, so it can be understood and tested on its own. This is usually the better fix.

Fix 2: the global keyword

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

beeps = 0

def beep():
    global beeps
    tone(880, 0.1)
    wait(0.1)
    beeps = beeps + 1

beep()
beep()
print("beeps:", beeps)

Run this in the simulator

global beeps tells Python that beeps in this function means the global one. It works, but now beep quietly changes something outside itself: a reader of the main program cannot see that beep() changes beeps, and any function anywhere could be the one that changed it. Use global sparingly, for a few values the whole program genuinely shares.

Task: count the beeps

This program should beep three times and print beeps: 3, but it crashes. Fix it, with parameters and return or with global.

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

beeps = 0

def beep():
    tone(880, 0.1)
    wait(0.1)
    beeps = beeps + 1

beep()
beep()
beep()
print("beeps:", beeps)

Challenges

  1. Write longest_so_far(reading, best) that returns whichever is larger, and use it in a loop of readings without any global variables.
  2. Add a global constant NOTE = 660 and use it inside beep. Why does reading it work without global?
  3. Find a program from an earlier lesson that uses variables inside a function, and say which are local and which are global.