The scope or the variable scope in Python is a part of a program where a certain variable is accessible. A variable scope can be categorized as Local, Enclosing, Global, or Built-in.
This Python Scope tutorial covers types of variable scope in Python, how they work, and how you can access variables from different scopes.
Table of contents
Local scope in Python
Whenever you define a variable within a function, its scope lies ONLY within the function. This type of scope is known as local scope. Local variables are variables that are declared in a local scope. Local variables are not known to the program outside the scope of the code block they are defined in. Calling a local variable outside its scope in Python generates an error the same as a not declared variable.
Let us take the following program as an example:
def print_num():
a = 10
print('Number inside the function:', a)
print_num()
print('Number outside the function:', a)
Running the above program outputs:
Number inside the function: 10
Traceback (most recent call last):
File "/home/hi/Desktop/local.py", line 6, in <module>
print('Number outside the function:', a)
NameError: name 'a' is not defined
From the program output above, the print statement in the function outputs the variable’s value while trying to print it causes the program to issue an error. The error NameError: name 'a' is not defined
indicates the the variable was either not accessible in the scope it is called in, or the variable is not declared.
Enclosing scope in Python
The scope inside a nesting function (a function that has another function inside it) is an enclosing scope. Local scope exists inside an enclosing scope, and variables declared in the enclosing scope can be accessed in the local scope.
Let us take the following program as an example:
def print_num():
a = 10
def print_num2():
b = 2
print('print_num2:', a)
print('print_num2:', b)
print_num2()
print('print_num:', b)
print_num()
Running the program above outputs:
print_num2: 10
print_num2: 2
Traceback (most recent call last):
File "/home/hi/Desktop/enclosing.py", line 9, in
print_num()
File "/home/hi/Desktop/enclosing.py", line 8, in print_num
print('print_num:', b)
NameError: name 'b' is not defined
From the previous example, both variables a
and b
are outputted to the screen from the nested function since variable a
is in the enclosing scope and can be accessed from the local scope and b
is declared and accessed inside the local scope. The third print statement generates an error because we are trying to access a variable inside an enclosing scope outside its scope and has not been declared outside the nested function.
Global scope in Python
Global scope is a scope outside any function. Variables declared here can be accessed by the whole program. They can be accessed both inside and outside functions.
Let us take another code as an example:
x = 10
def printer():
print(x)
printer()
print(x)
The output is as follows:
10
10
The program above outputs the value of x
when it is called both in a local scope (in the function) and global scope. This demonstrates that a global variable is accessible anywhere within the code.
Built-in scope in Python
The built-in scope is the widest of them all. The built-in scope is the scope of variables and keywords in the Python language library. Programs can access variables or keywords in this scope without being declared in the program code.
Keywords are special reserved words used by Python. Examples of keywords include: for
, while
, if
, else
, and in
LEGB Rule
LEGB rule is the logic that the Python interpreter follows when executing a program. It stands for Local Enclosing Global Built-in, and the order of their execution is respectively.
Let us take consider the program below:
x = 0
def printer():
x = 1
def inner_printer():
x = 2
print('inner_printer:', x)
inner_printer()
print('printer:', x)
printer()
print('global:', x)
When we run the program, the output is as follows:
inner_printer: 2
printer: 1
global: 0
As we can observe, even though the variable is declared differently in all the scopes, Python always checks the for the variable in the current scope the moves up the ladder. The following chart shows how the Python interpreter checks for variables inside a program:

The analogy presented above might sometimes cause problems. Let us take the following scenario as an example:
We want to write a function that modifies a global variable. For example:
h = 'bake bread'
def cake():
h = 'bake cake'
cake()
print(h)
The program above outputs as follows:
bake bread
Why do u think this happened? There is a simple explanation for this when we set the value of h to ‘bake cake,’ Python created a new local variable named h in the scope of cake(). This does not modify the value of the global variable h. Cases like this are where the global
keyword comes in handy.
Global keyword
The global
keyword tells Python to use the global variable instead of creating one locally. Using the global
keyword, we can now correct Scenario 1 to the way we want it. The following code is the modified version of Scenario 1:
h = 'bake bread'
def cake():
global h
h = 'bake cake'
cake()
print(h)
The program above outputs as follows:
bake cake
Now we can finally bake some cake?!!!
Nonlocal keyword
Let us consider another scenario:
We want to change the value of a variable in an enclosing scope. For example:
def outer():
greet = 'Hi'
def inner():
greet = 'Bye'
inner()
print(greet)
outer()
The program above outputs as follows:
Hi
Cases like this can be corrected using the nonlocal
keyword. The nonlocal
keyword causes the variable to refer to the previously bound variable in the closest enclosing scope. In other words, it will prevent the variable from trying to bind locally first and force it to go a level ‘higher up’. Its syntax is the same as the global
keyword.
The following code corrects Scenario 2:
def outer():
greet = 'Hi'
def inner():
nonlocal greet
greet = 'Bye'
inner()
print(greet)
outer()
The output is as follows:
Bye
Yay, the program can finally say Bye
!!!
Summary
This article covered types of variable scopes in Python, how they work, and how you can access variables from different scopes. In addition, we’ve introduced the LEGB rule, which will help you imagine Python scope boundaries when you’re developing your Python programs.