Scope
As your programs grow larger and your functions become more complex a natural question starts to emerge. Where can I actually use this variable? The answer depends on something called scope.
Scope refers to the part of your program where a variable exists and can be accessed. Not every variable is available everywhere in your code. Where you define a variable determines where you can use it.
Python has four levels of scope and they are evaluated in a specific order known as the LEGB rule:
- L - Local variables defined inside the current function
- E - Enclosing variables defined in any enclosing functions
- G - Global variables defined at the top level of the file
- B - Built in names that are part of Python itself like
print,lenandrange
When Python encounters a variable name it searches through these four levels in order, starting with Local and working outward. The first match it finds is the one it uses.
Local Scope
A variable created inside a function is local to that function. It only exists while the function is running and cannot be accessed from outside it. Once the function finishes the variable is gone.
The variable message only exists inside
greet(). Trying to print it outside the function throws
a NameError because as far as the rest of the program
is concerned that variable does not exist.
Global Scope
A variable created at the top level of your file, outside of any function, is global. It can be read from anywhere in the file including inside functions. However reading a global variable and modifying it are two different things.
The function can read language because it is global.
But if you try to reassign it inside the function without telling
Python explicitly, it will create a new local variable with the
same name instead of modifying the global one. This is one of the
most common sources of confusion around scope.
Both print statements print Python because the
assignment inside the function created a new local variable called
language that only exists inside the function. The
global language was never touched.
The global Keyword
If you genuinely need to modify a global variable from inside a
function you can use the global keyword
to tell Python explicitly that you want to work with the global
version rather than creating a local one.
Use the global keyword sparingly. Modifying global
variables from inside functions makes your code harder to follow
and debug because the value of the variable can change from anywhere
in the program. In most cases it is better to pass values in as
arguments and return results instead.
Enclosing Scope
Enclosing scope applies when you have a function defined inside another function. The inner function has access to variables defined in the outer function even though they are not global. This is the E in LEGB.
The inner function inner() can read name
from the outer function even though it was not passed in as an
argument. This is enclosing scope in action.
The nonlocal Keyword
Just as global lets you modify a global variable from
inside a function, the nonlocal keyword
lets you modify a variable from an enclosing function rather than
creating a new local one.
Without nonlocal, the assignment inside
inner() would create a new local variable called
count and the outer count would remain
unchanged. With nonlocal, Python knows to modify the
variable in the enclosing scope.
Built in Scope
The outermost level of scope is built in scope.
This contains all the names that Python provides automatically
without you having to define or import anything. Functions like
print(), len(), range(),
type() and input() all live in built in
scope. They are always available everywhere in your program.
This is also why you should never name your own variables or
functions the same as a built in. If you create a variable called
list or print you will shadow the built
in and Python will use your version instead, which will almost
certainly cause unexpected behaviour.
Time to experiment!
Coding Exercises (VS Code) Instructions:
- Create a file named scope.py in your part57 folder.
- Complete the tasks and use # comments to explain your answers.
Exercise 1: Local vs Global
-
Task: Create a global variable
country = "Thailand"and a function calledshow_country(). -
Goal: Inside the function create a local variable
also called
countrywith a different value. Print the local version inside the function and the global version outside it. Write a comment explaining why both print statements produce different results even though the variable has the same name.
Exercise 2: The global Keyword
-
Task: Create a global variable
high_score = 0and a function calledupdate_score(new_score). -
Goal: Use the
globalkeyword inside the function to updatehigh_scoreifnew_scoreis greater than the currenthigh_score. Call the function three times with different scores and printhigh_scoreafter each call to verify it is being updated correctly. Write a comment explaining what would happen if you removed theglobalkeyword.
Exercise 3: Enclosing Scope
-
Task: Create a function called
outer()that defines a variablemessage = "Hello from outer"and contains an inner function calledinner(). -
Goal: Inside
inner()printmessagewithout passing it as an argument. Callouter()and verify thatinner()can access the variable from the enclosing scope. Write a comment explaining the difference between enclosing scope and global scope.
Exercise 4: The nonlocal Keyword
-
Task: Create a function called
counter()that defines a variablecount = 0and contains an inner function calledincrement(). -
Goal: Use the
nonlocalkeyword insideincrement()to increasecountby 1 each time it is called. Callincrement()five times insidecounter()and printcountafter each call. Write a comment explaining what would happen if you removed thenonlocalkeyword and why.
Exercise 5: Spot the Scope Bug
- Task: The following code has a scope related bug. Find it, fix it and explain why it caused a problem:
score = 0def add_points(points):score = score + pointsreturn scoreprint(add_points(10))
-
Goal: Fix the bug and write a comment explaining
why Python threw an error and what the correct solution is. Then
write a second version of the function that avoids using the
globalkeyword entirely by passingscoreas a parameter instead.
Don't Forget to commit and Push!