Python Foundations

Local & Global Variables

Variable scope: where a variable lives and why it matters. Local variables (private to a function), global variables (program-wide state), the same-name shadowing trap, the global keyword for modifying globals, and when to choose local vs global.

6.1 Local Variables

If every variable in a program were visible everywhere, large programs would be impossible to debug — any line could change anything. The whole point of putting code inside a function is that the function's variables are its own business. Cambridge expects you to write efficient pseudocode (Section 11.3, AS Level), and that explicitly means declaring data locally where only that routine needs it.

A local variable is one declared inside a function. Two important facts follow:

  • Lifetime. The variable comes into existence when the function starts running and is destroyed when the function ends. The next call gets a fresh variable.
  • Visibility. Code outside the function cannot see the variable at all. Trying to use it produces a NameError in Python (or an undeclared-variable error in pseudocode).

Python — local stays local

def greet():
    message = "Hello, World!"  # local variable
    print(message)

greet()              # prints "Hello, World!"
print(message)       # NameError: name 'message' is not defined

Pseudocode — local stays local

PROCEDURE Greet()
    DECLARE message : STRING
    message <- "Hello, World!"
    OUTPUT message
ENDPROCEDURE

CALL Greet()
OUTPUT message  // ERROR — message does not exist here
Key rule — locals are private:
  • A local variable is invisible outside the function it belongs to.
  • This is a feature, not a limitation — it stops other parts of the program from accidentally damaging the function's working values.

Worked example — local variable and the outside error

Task: Write a Python function calculateSum that uses a local variable total to add the integers 15 and 27, then prints the result. State what happens if you try to print total immediately after calling the function. [3 marks]

def calculateSum():
    total = 15 + 27     # local variable
    print(total)        # 42

calculateSum()         # prints 42
print(total)           # NameError: name 'total' is not defined
Exam tip:
  • When a Cambridge question asks "what is the output / explain the error", a 1-mark answer is just "NameError" or "undeclared".
  • The full mark answer says why — "because the variable is local to the function and goes out of scope when the function ends".
  • Always give the reason.
Your Turn — Local variable and the outside error [3 marks]
Write a Python function calculateArea that uses a local variable area to store the product of length = 8 and width = 5, then prints the result. State what happens if you print area after the call.
Hint:
  • A local variable is declared inside the function
  • The print happens inside the function
  • Outside the function, the variable does not exist → error

6.2 Global Variables

Sometimes the whole program needs to share a piece of state — a player's score, a bank balance, a connection setting. These values belong to the program as a whole, not to any single function. That is exactly what a global variable is for.

A global is declared outside every function. Any function can read its value just by using the name. Modifying it from inside a function needs an extra step in Python (see section 6.4).

Python — reading a global is automatic

count = 0  # global variable

def showCount():
    # reads the global — no keyword needed
    print("Inside function:", count)

showCount()
print("Outside function:", count)

# Output:
# Inside function: 0
# Outside function: 0

Pseudocode — global declared at the top

DECLARE count : INTEGER  // global

PROCEDURE ShowCount()
    OUTPUT "Inside procedure: ", count
ENDPROCEDURE

count <- 0
CALL ShowCount()
OUTPUT "Outside procedure: ", count
Key rule — reading versus changing:
  • Inside a function you can read a global just by using its name.
  • But to change a global from inside a function in Python you need the global keyword — otherwise Python creates a brand-new local variable with the same name and leaves the global alone.
  • (See section 6.4.)

Worked example — reading a global

Task: A program has a global integer score initialised to 0. Write a Python function showScore that prints the current value of score. Then set score to 50 and call showScore to verify it can see the new value. [3 marks]

score = 0  # global

def showScore():
    # reads the global — Python finds it automatically
    print("Score is:", score)

score = 50        # change the global from outside — no keyword needed
showScore()       # Score is: 50
Exam tip:
  • In Cambridge pseudocode there is no need for the GLOBAL keyword to read a global — the rules are looser than Python's.
  • GLOBAL is only needed when a question explicitly asks the procedure to change a global.
  • Don't sprinkle GLOBAL everywhere "just in case" — it costs marks for clarity.
Your Turn — Reading a global [3 marks]
A program has a global integer level initialised to 1. Write a Python function showLevel that prints "Current level: [level]". Then set level to 5 and call the function.
Hint:
  • Global is declared at the top of the program
  • The function reads it (no keyword needed)
  • You change it from outside the function

6.3 Same-Name Conflict (Shadowing)

This is one of the most common "predict the output" trap questions on Paper 4. The function looks like it changes the global — but it does not, because a new local has shadowed it.

If a function assigns to a variable with the same name as a global, the function creates a brand-new local variable. The global is unchanged. Inside the function, the name refers to the local; outside, the name still refers to the global.

Python — shadowing

x = 10  # global

def changeX():
    x = 5  # NEW local — global x is untouched
    print("Inside function:", x)

changeX()              # Inside function: 5
print("Outside function:", x)  # Outside function: 10

Pseudocode — shadowing

DECLARE x : INTEGER  // global

PROCEDURE ChangeX()
    DECLARE x : INTEGER  // new local, shadows global
    x <- 5
    OUTPUT "Inside procedure: ", x
ENDPROCEDURE

x <- 10
CALL ChangeX()
OUTPUT "Outside procedure: ", x  // 10
Key rule — shadowing:
  • When a local variable has the same name as a global, the local hides (shadows) the global inside that function.
  • The global still exists; it just cannot be seen from inside the function while the local is in scope.

Worked example — Alice / Bob / Alice

Task: A program defines a global name = "Alice". A procedure changeName declares a local name = "Bob" and prints it. Trace the output of: print name; call changeName; print name. Explain why. [4 marks]

  • Step 1 — First print, before the call: outside any function, name refers to the global, which is "Alice".
  • Step 2 — Inside the procedure: the procedure declares its own name and assigns "Bob". This is a brand-new local that shadows the global. The print inside the procedure uses this local.
  • Step 3 — Second print, after the call: the local name was destroyed when the procedure ended. The global name was never touched — it is still "Alice".
Exam tip:
  • Final answer (full output): Alice / Bob / Alice.
  • Reason: the procedure created a new local name; that local hid the global only inside the procedure; the global was never assigned to, so it kept its original value.

The UnboundLocalError trap

A subtle Python trap: total = total + 50 inside a function. Python sees total = ... as a local assignment. But the right-hand side total + 50 tries to read total before the local has been assigned — this raises UnboundLocalError.

Broken version — UnboundLocalError

total = 100

def addBonus():
    # total = ... makes total a LOCAL.
    # RHS reads local before assigned -> ERROR
    total = total + 50
    return total

print(addBonus())  # UnboundLocalError

Fixed version — different local name

total = 100

def addBonus():
    # read global (no assignment to total)
    # write a NEW local called newTotal
    newTotal = total + 50
    return newTotal

print(total)       # 100
print(addBonus())  # 150
print(total)       # 100 — global unchanged
Exam tip: In a Cambridge "predict the output" question with both a local and a global of the same name, the safe rule is: inside the function, the local always wins; outside, the global is untouched unless the function explicitly used global (Python) or GLOBAL (pseudocode).
Your Turn — The UnboundLocalError trap — fixed version [4 marks]
A program defines a global integer total = 100. A function addBonus should return total + 50 WITHOUT changing the global. Write the safe version that reads the global and returns the new value.
Hint:
  • Read the global (no assignment to total)
  • Write a NEW local called newTotal
  • Return newTotal

6.4 Modifying a Global Inside a Function

Section 6.3 showed that assigning to a name inside a function normally creates a local. But what if you really do want the function to change the global? You have to tell the language that is what you mean. In Python the keyword is global. In Cambridge pseudocode it is GLOBAL.

Python — the global keyword

score = 100  # global

def addBonus():
    global score  # declare intent — modify the global
    score = score + 10  # updates the global, not a local

addBonus()
print(score)  # 110

Pseudocode — the GLOBAL keyword

DECLARE score : INTEGER  // global

PROCEDURE AddBonus()
    GLOBAL score
    score <- score + 10
ENDPROCEDURE

score <- 100
CALL AddBonus()
OUTPUT score  // 110
Why global is needed here: Without global score, the line score = score + 10 would create a brand-new local score and try to read it before assignment — exactly the UnboundLocalError from section 6.3.

Worked example — earnMoney

Task: A program uses a global integer money initialised to 50. Write a Python function earnMoney that adds 20 to money by modifying the global directly. Call the function and verify the global has changed. [3 marks]

money = 50  # global

def earnMoney():
    global money          # this function will modify the global
    money = money + 20

print("Before:", money)   # 50
earnMoney()
print("After: ", money)   # 70
Key rule — be deliberate:
  • Use global / GLOBAL only when the function genuinely needs to change the global.
  • If the function only needs to compute a new value, return it instead and let the caller assign.
  • Returning is almost always cleaner and easier to test.
Exam tip:
  • Cambridge frequently asks "explain why this function does not change the global variable".
  • The model answer always names the cause: the function assigned to a local of the same name; to actually modify the global, the function would need the global (Python) or GLOBAL (pseudocode) keyword.
Your Turn — Modifying a global with the global keyword [3 marks]
A program uses a global integer fuel initialised to 100. Write a Python function burnFuel that subtracts 15 from fuel by modifying the global. Show output before and after the call.
Hint:
  • Same shape as the earnMoney Worked Example
  • Change the operation from + 20 to - 15
  • Use the global keyword to modify the global

6.5 Local vs Global — When to Use Which

Cambridge "discuss" and "explain" questions on Paper 3 and Paper 4 often ask for two advantages of local variables, or two reasons to prefer return values over global modification. You need to have the answers ready in your own words.

FeatureLocal variableGlobal variable
ScopeInside one function onlyAnywhere in the program
LifetimeCreated on call, destroyed on returnExists for the whole program run
Memory useTemporary — released after the callHeld for the entire program
Risk of accidental changeNone — only the owning function can see itHigh — any function with the keyword can change it
Best forWorking values, loop counters, intermediate resultsProgram-wide state (e.g. balance, score, settings)

Three rules of thumb

  • Prefer local. If a function can do its job with local variables and a return value, do that. The code is easier to test and easier to reuse.
  • Use global only when the value really is program-wide. Examples: bank balance, current player score, login state.
  • Never modify a global silently. If a function changes a global, that fact should be obvious from its name (addBonus, deposit, resetScore). A function named calculateSum should not secretly change a global.
Key rule — efficient pseudocode:
  • Section 11.3 (AS Level) explicitly requires you to "write efficient pseudocode".
  • One marker of efficiency is correct scope — variables declared where they are needed, not at the top of the program "just in case".
  • Locals win.

6.6 Putting It Together — Bank Account

This is the standard Paper 4 "extend the existing program" question type — you are given a small system with global state and must add functions that read or modify that state correctly. A bank account simulator with a global balance and three operations.

Python version

balance = 1000  # global

def deposit(amount):
    global balance
    balance = balance + amount
    print(f"Deposited {amount}. New balance: {balance}")

def withdraw(amount):
    global balance
    if amount <= balance:
        balance = balance - amount
        print(f"Withdrew {amount}. New balance: {balance}")
    else:
        print("Insufficient funds.")

def checkBalance():
    # reads global — no "global" needed
    print(f"Current balance: {balance}")

deposit(500)      # Deposited 500. New balance: 1500
withdraw(200)     # Withdrew 200. New balance: 1300
checkBalance()    # Current balance: 1300
withdraw(5000)    # Insufficient funds.

Pseudocode version

DECLARE balance : INTEGER  // global

PROCEDURE Deposit(amount : INTEGER)
    GLOBAL balance
    balance <- balance + amount
    OUTPUT "Deposited ", amount, ". New balance: ", balance
ENDPROCEDURE

PROCEDURE Withdraw(amount : INTEGER)
    GLOBAL balance
    IF amount <= balance THEN
        balance <- balance - amount
        OUTPUT "Withdrew ", amount, ". New balance: ", balance
    ELSE
        OUTPUT "Insufficient funds."
    ENDIF
ENDPROCEDURE

PROCEDURE CheckBalance()
    OUTPUT "Current balance: ", balance
ENDPROCEDURE
Why deposit and withdraw need GLOBAL but checkBalance does not:
  • deposit and withdraw modify the global balance, so they need global balance.
  • checkBalance only reads it, so no keyword is needed.
  • This distinction is a common exam question.

Key Points Summary

A local variable is declared inside a function — it is private to that function.
Local lifetime: created on call, destroyed on return. The next call gets a fresh variable.
Using a local from outside its function raises NameError (Python) / undeclared error (pseudocode).
A global variable is declared outside every function — the whole program can read it.
Reading a global is automatic in Python (no keyword). Changing it needs "global".
In pseudocode, GLOBAL is only needed to CHANGE a global — not to read one.
Shadowing: assigning to a name inside a function creates a NEW local; the global is untouched.
total = total + 50 inside a function (no global) raises UnboundLocalError.
The "global" keyword tells Python the name refers to the global — assignments then update it.
Prefer local + return value over modifying a global whenever possible (easier to test and reuse).
Use globals only for genuine program-wide state: balance, score, login state.
Never modify a global silently — the function name should make it obvious (deposit, addBonus).
"Efficient pseudocode" (Section 11.3) = declare variables where they are needed — locals win.

6.7 Practice Tasks

Fifteen exam-style scope tasks. Each shows only the question — click Hint for the thought process, or Help for the worked solution. Try each one yourself before revealing.

Exam tip:
  • For every scope task, the marker checks: (1) correct use of global when modifying a global, (2) understanding that locals are private to their function, (3) recognising shadowing and UnboundLocalError.
  • The most common mark loss is forgetting global when a function must change a global.
1Practice Task — Declare and use a local variable [2 marks]
Write a Python function showLocal() that declares a local variable message = "Hi there" and prints it. Call the function.
2Practice Task — Local variable outside the function [2 marks]
A function declares name = "Alice" inside it. What happens if you try print(name) in the main program after calling the function? Explain why.
3Practice Task — Read a global from inside a function [3 marks]
Write a Python program with a global variable score = 100. Write a function showScore() that prints the value of score. Call the function.
4Practice Task — Shadow a global with a local [3 marks]
A global x = 10 exists. Write a function changeX() that assigns x = 5 inside it and prints x. Call the function, then print x in the main program. State both outputs.
5Practice Task — Modify a global with the global keyword [3 marks]
A global score = 100 exists. Write a function addBonus() that adds 10 to score by modifying the global. Call the function and print score before and after.
6Practice Task — Predict the output — shadowing [4 marks]
Trace the output of this program: name = "Alice" def changeName(): name = "Bob" print(name) print(name) changeName() print(name)
7Practice Task — Fix the UnboundLocalError [4 marks]
This code raises UnboundLocalError. Fix it WITHOUT using the global keyword — use a different local name and return the result. total = 100 def addBonus(): total = total + 50 return total
8Practice Task — Global counter — increment [3 marks]
Write a program with a global counter = 0. Write a function increment() that adds 1 to counter each time it is called. Call it 3 times and print counter.
9Practice Task — Bank balance — deposit [4 marks]
Write a program with a global balance = 1000. Write a function deposit(amount) that adds amount to balance and prints the new balance. Call deposit(500).
10Practice Task — Bank balance — withdraw with condition [5 marks]
Write a function withdraw(amount) that subtracts amount from the global balance ONLY if there are enough funds. Otherwise print "Insufficient funds." Call withdraw(200) then withdraw(5000).
11Practice Task — Score tracker — multiple functions [5 marks]
Write a program with a global score = 0. Write two functions: addPoints(n) that adds n to score, and showScore() that prints the current score. Call addPoints(10), addPoints(5), showScore().
12Practice Task — Temperature converter — local + return [4 marks]
Write a function toFahrenheit(celsius) that takes a temperature in Celsius and returns the Fahrenheit equivalent (F = C * 9/5 + 32). Use only LOCAL variables. Call it with 25 and print the result.
13Practice Task — Decide local or global [4 marks]
For each scenario, state whether you would use a LOCAL or GLOBAL variable and why: (a) A loop counter inside a function (b) A bank balance shared by deposit and withdraw functions (c) A running total calculated inside one function (d) A player's score updated by multiple functions in a game
14Practice Task — Explain why the global is unchanged [4 marks]
A student writes: count = 5 def addToCount(): count = count + 1 addToCount() print(count) They expect 6 but get an error. Explain the error and fix it two ways: (a) using global, (b) using return.
15Practice Task — Convert global-modifying to return [5 marks]
This function uses a global. Rewrite it to use ONLY local variables and a return value instead. Show the calling code. result = 0 def calculateSquare(n): global result result = n * n

Question Bank

Answer all questions, then press Submit Quiz to see your score.

0/12 answered

Question 1Multiple Choice

Where is a local variable declared?

Question 2True / False

A local variable is destroyed when its function ends — the next call gets a fresh variable.

Question 3Multiple Choice

In Python, what error do you get if you try to use a function's local variable from outside the function?

Question 4Multiple Choice

In Python, what do you need to CHANGE a global variable from inside a function?

Question 5True / False

When a local variable shadows a global, the global is destroyed permanently.

Question 6Multiple Choice

What is the output? x = 10 def changeX(): x = 5 print("Inside:", x) changeX() print("Outside:", x)

Question 7Multiple Choice

What is the output? score = 100 def addBonus(): global score score = score + 10 addBonus() print(score)

Question 8True / False

In Cambridge pseudocode, the GLOBAL keyword is needed only when a procedure must CHANGE a global — not just to read one.

Question 9Multiple Choice

Which is the BEST choice for a loop counter used inside a function?

Question 10True / False

A function named calculateSum should be allowed to secretly modify a global called total.

Question 11Multiple Choice

What does this Python code do? total = 100 def addBonus(): total = total + 50 return total

Question 12True / False

You should prefer local variables and return values over modifying globals whenever possible.

Answer all 12 questions to enable submission.