In previous articles, we learned about following topics:
Understanding Scope in Programming
- The part of a program where a variable name can be accessed is called its scope.
- Scope defines the area of the program in which a name can be accessible and different operations can be performed on that name.
- Name can be of a variable, function, class or any object.
- In the scope, we can use the given name to perform different operations like access, update and delete.
- Not all variables are accessible from every part of the program.
Generally, in the scope of a program, a variable can be declared only once with the same name. But, it’s possible to declare variables with the same name in different scopes within the same program. Changing the value of a variable within a scope, does not impact its value outside that scope, even if the variables are of same name.
Scope of Code Blocks in Programming
- Code block is defined as an area, which is separated from other sections or blocks of the program. For example: in a program, functions, classes, conditional statements and, loops are independent or separate code blocks.
- In Python, all variables are scoped to the code block, it means
- In the code block, the variable can be declared and assigned values.
- Variables can be accessed, updated and deleted within that code block.
- Python uses indentation to define a code block, it grouped the code under its parent statements like function, class, module or script file.
Understanding Variable Scope in Python
Python offers various levels of variable scope, each determining where a variable can be accessed and modified:
- Local Scope
- Global Scope (using the global keyword)
- Nonlocal Scope (using the nonlocal keyword)
- Enclosing Scope
- Built-In Scope
- In Python, “local scope” is the default scope, which also referred to as the “scope of the code block.“
- Unless otherwise specifically defined, all variables declared within a code block have local scope.
Python’s global keyword is used for modifying a variable’s scope when necessary. This “global” keyword is of significant use when working with scopes for a variable.

Local Scope in Python
Description of Local Scope:
- Variables with local scope are declared inside a code block.
- Variables declared within this code block have local scope, which is specific to that declaration block only.
- Local variables cannot be accessed outside the block in which they were declared.
Program – Local Scope Example
Lets understand local scope in Python with a program.
def func_local_variable():
shbytes_local = "This is local variable!!"
print(shbytes_local)
func_local_variable()
print(shbytes_local)
Output of the local scope program
Traceback (most recent call last):
File "D:\local_scope.py", line 7, in <module>
print(shbytes_local)
^^^^^^^^^^^^^
NameError: name 'shbytes_local' is not defined
This is local variable!!
Let’s understand local scope with a program. Here, we define a variable named shbytes_local. This variable is declared inside the function func_local_variable(). This makes this variable local to this function, which means this variable can only be accessed within func_local_variable().
We print the shbytes_local variable’s value inside func_local_variable(), where its value is displayed. But when we are trying to print shbytes_local outside of the function, then it results in a NameError – indicating that the variable shbytes_local is not available outside its defined function.
Key Points from the above program:
- By default, a variable has a local scope and is accessible only within its local scope.
- The local scope is defined by the block or area where the variable is declared.
- Attempt to access a variable outside of its scope will generate an error.
Examples of Local Scope in Python
Variables can be declared outside of any code block, which gives them a larger scope. This allows them to be used with in the sub-code blocks as well. Below are examples of local scope used with functions, classes and modules.
Variable Declared Directly inside a Function
- Variables declared directly inside a function can be accessed inside the sub code blocks of that function.
- These variables can be accessible inside the conditional statements and loops which are inside that function.
- These variables can also be passed as arguments to other functions from within the defined function.
Program – Function Local Scope Variable
def local_function_scope_variable():
shbytes_local = 0
while(shbytes_local < 10):
shbytes_local += 1
if(shbytes_local %2 == 0) :
print(f'{shbytes_local} is Even')
else:
print(f'{shbytes_local} is Odd')
local_function_scope_variable()
Program Output – Function Local Scope Variable:
1 is Odd
2 is Even
3 is Odd
4 is Even
5 is Odd
6 is Even
7 is Odd
8 is Even
9 is Odd
10 is Even
Variable declared directly inside a Class
- Variables can be declared directly inside a Class, called as class level variables
- These class level variables can be accessed directly inside the class
- These variables can be passed as an argument to the functions using the class scope
Program – Class Local Scope Variable
class Shbytes:
shbytes_local = 0
print(shbytes_local)
def func_scope_variable(number):
while (number < 10):
number += 1
if (number % 2 == 0):
print(f'{number} is Even')
else:
print(f'{number} is Odd')
Shbytes.func_scope_variable(Shbytes.shbytes_local)
Program Output – Class Local Scope Variable:
0
1 is Odd
2 is Even
3 is Odd
4 is Even
5 is Odd
6 is Even
7 is Odd
8 is Even
9 is Odd
10 is Even
Points to Note from the Program Example:
- The variable
shbytes_localis directly accessible within the Class where it was declared. This variable value can be printed directly from the Class. - This variable
shbytes_local, can also be accessed using class name likeShbytes.shbytes_localand can be passed as a function argument.
Variables declared directly inside Module
- Variables declared directly within a module are accessible throughout the module.
- However, they are limited to the module boundary, meaning variables from one module cannot be used in another module.
Program – Module Local Scope Variable
shbytes_global = "This is global variable!!"
def func_global_variable():
print(shbytes_global)
func_global_variable()
print(shbytes_global)
Program Output – Module Local Scope Variable
This is global variable!!
This is global variable!!
In the example, we defined a variable shbytes_global outside of any code block, directly within the module. This allows shbytes_global to be used anywhere within the module, and we demonstrate this by printing its value inside func_global_variable().
The global Keyword in Python
We can declare two different variables with the same name at different scope levels. For instance, a variable with name x can be declared both as a global variable and another variable x declared as local variable at different scope level.
But the same variable cannot have two scopes at the same time. A variable can only have either a global scope or local scope. The global keyword allows a local variable to be promoted to a global variable.
Program – global Keyword Example
def func_local_variable():
global shbytes_local # declared locally but made global
shbytes_local = "This is local variable with global scope!!"
print(shbytes_local)
func_local_variable()
print(shbytes_local)
In this example, the variable shbytes_local is defined within the function func_local_variable() but declared using the global keyword. Although the variable is defined locally, the global keyword allows this variable to be accessed outside of the function scope. When we print the value of shbytes_local outside the func_local_variable() function, the value can still be accessed and printed.
Program Output – global Keyword Example
This is local variable with global scope!!
This is local variable with global scope!!
If we hadn’t defined the variable shbytes_local with the global keyword, as done in the local scope example, it would have resulted in a NameError: name ‘shbytes_local’ is not defined.
Enclosing Scope in Python
Enclosing scope is significant while working with nested functions. In nested functions, variables declared in an outer function have a higher scope. This means, variables declared in an outer function, can be used in an inner function, but variables declared in an inner function, cannot be accessed in the outer function.
Due to this enclosing scope, variables declared in a function are only accessible within that function and its nested child functions.
Also, although variables declared in an outer function can be accessed in an inner function, any changes to the outer variable’s value within the inner function will remain local to the inner function and won’t affect the variable value in outer function.
- A program always uses the variable, whose scope is closest to it.
- This concept of enclosing scope does not apply to the nested structure of if statements and loops..
Program 1 – Enclosing Scope Example
def outer():
outer_counter = 1
def inner():
inner_counter = 2
print("outer counter : ", outer_counter)
print("inner counter : ", inner_counter)
inner()
print("outer counter in func_outer : ", outer_counter)
outer()
Program 2 – Enclosing Scope Example
def outer():
outer_counter = 1
def inner():
inner_counter = 2
outer_counter = 3
print("outer counter : ", outer_counter)
print("inner counter : ", inner_counter)
inner()
print("outer counter in func_outer : ", outer_counter)
outer()
- In Program 1, we are not updating the value of the variable
outer_counterin theinner()function, but in Program 2, we are updating the value of the variableouter_counterin theinner()function. - In both programs, we can access the variable
outer_counterinside theinner()function. However, in Program 2, when we re-declare the variableouter_counterinside theinner()function, thisouter_countervariable will use it’s closest scope which is local scope. So,outer_countervariable defined withininner()function will be a separate variable with local scope. - In Program 2, although both variables share the same name,
outer_counter, but they both are distinct variables. - The program will always use the variable closest to its scope.
Output of the above programs for enclosing scope
outer counter : 1
inner counter : 2
outer counter in func_outer : 1
outer counter : 3
inner counter : 2
outer counter in func_outer : 1
- From the output of Program 1, variable
outer_counteralways refers to the variable declared in theouter()function, so its value is consistently 1. - In Program 2, within the
inner()function,outer_counterrefers to the variable withinner()function scope, whereas in theouter()function,outer_counterrefers to theouter()function scope. Hence, their values are different => 3 and 1.
If we want to use the same variable declared in the outer() function without re-declaring it in the inner() function, we can use the nonlocal keyword.
nonlocal Keyword in Python
In the enclosing scope section, we have observed:
- A variable with the same name declared inside an
innerfunction is treated as a new variable with the inner function’s scope. - If we don’t want to declare another variable with the same name inside
innerfunction but want to use the same variable declared inouterfunction, then we can usenonlocalkeyword.
Properties of nonlocal Keyword
- The
nonlocalkeyword was introduced from Python 3. nonlocalkeyword addresses the limitations of the enclosing scope.- Using
nonlocalkeyword, variables declared in outer function can be used in inner function and their values can be changed inside the inner function, which will be reflected to outer function as well. - The nonlocal keyword works only with variables declared in a nested function structure.
- It cannot be used to change the variables declared with module scope.
- In nested functions, nonlocal variables refer to the closest parent variable in the hierarchy and will take the first reference that it found in its parent scope.
- If no variable reference exists in the parent hierarchy of nested functions, a
SyntaxErroris raised: “no binding fornonlocal‘variable_name’ found”.
nonlocal Program to Understand Parent Hierarchy
Let’s understand how the reference for a nonlocal variable is taken from its parent hierarchy through an example.
- If no variable is present in the parent hierarchy then
SyntaxErrorwill be raised.
Program 1
def nonlocalscope():
nonlocal a
a = "changing to non-local!"
print(a)
a = "global variable!"
nonlocalscope()
Program 2
def localscope():
a = "local variable!"
def nonlocalscope():
nonlocal a
a = "changing to non-local!"
print(a)
nonlocalscope()
print(a)
localscope()
In Program 1, we define a function named nonlocalscope() where we declare a nonlocal variable a. Since a is not declared within any parent hierarchy function, and variables declared at the module level can’t be assigned as nonlocal, it results in a SyntaxError – “no binding for nonlocal ‘a’ found.”
In Program 2, we use a nested function structure. Here, the variable a is declared in the outer localscope() function, and a nonlocal variable a is declared in its inner nonlocalscope() function. Using nonlocal in the inner function will not declare a new variable but will instead search for a in the parent scope. When it finds the reference in the parent localscope() function, it uses that reference.
By using the parent hierarchy reference, if we modify the variable value in the inner function, the change is reflected in the outer function as well—something that wasn’t possible with just the enclosing scope. If no reference for the variable a is found in its parent hierarchy, it raises a SyntaxError – “no binding for nonlocal ‘a’ found.”
Output of the above programs for enclosing scope
File "D:\nonlocal_hierarchy.py", line 2
nonlocal a
^^^^^^^^^^
SyntaxError: no binding for nonlocal 'a' found
changing to non-local!
changing to non-local!
- From the Program 1 output, it throws a
SyntaxError– “no binding for nonlocal ‘a’ found.” - From the Program 2 output, the value for variable
afrom thelocalscope()function is changed and printed twice.
nonlocal Program to Understand Its Scope
In this program, the same concepts are used as explained in the previous section.
Program 1
def func_outer():
outer_counter = 1
print("outer counter in func_outer : ", outer_counter)
def func_inner():
inner_counter = 2
outer_counter = 3
print("outer counter : ", outer_counter)
print("inner counter : ", inner_counter)
func_inner()
print("outer counter in func_outer : ", outer_counter)
func_outer()
Program 2
def func_outer():
outer_counter = 1
print("outer counter in func_outer : ", outer_counter)
def func_inner():
inner_counter = 2
nonlocal outer_counter
outer_counter = 3
print("outer counter : ", outer_counter)
print("inner counter : ", inner_counter)
func_inner()
print("outer counter in func_outer : ", outer_counter)
func_outer()
- In Program 1, the variable
outer_counteris declared in thefunc_outer()function. We are using this variable inside thefunc_inner()function without thenonlocalkeyword. This program’s output will be similar to the enclosing scope program output, as explained previously. - In Program 2, the variable
outer_counteris declared in thefunc_outer()function, and we are usingouter_countervariable inside thefunc_inner()function with thenonlocalkeyword. In this case, theouter_countervariable will be referenced from the declaration in its parentfunc_outer()function.
Output of the above programs for nonlocal keyword
outer counter in func_outer : 1
outer counter : 3
inner counter : 2
outer counter in func_outer : 1
outer counter in func_outer : 1
outer counter : 3
inner counter : 2
outer counter in func_outer : 3
Built-in Scopes in Python
Python also has a built-in scope that does not apply to user-defined variables. Built-in scope is the widest scope and applies to all available special reserved keywords. We can call these keywords from anywhere in the programs or from any modules. These keywords are part of the Python core installation, reserved for specific purposes, and cannot be used for any other purpose in the program.
Reserved keywords are:
- False
- None
- True
- and
- as
- assert
- break
- class
- continue
- def
- del
- elif
- else
- except
- finally
- for
- from
- global
- if
- import
- in
- is
- lambda
- nonlocal
- not
- or
- pass
- raise
- return
- try
- while
- with
- yield
Summary
This article explains the concept of scope in programming, focusing on variable scopes in Python. It defines scope as the context in which a variable is accessible, detailing the types of scopes in Python: local, global, nonlocal, enclosing and built-in. Local variables are confined to their specific code blocks, while global variables can be accessed throughout the module. The article also discusses the nonlocal keyword, which allows inner functions to reference and modify variables from outer functions. Through clear examples, readers will understand the significance of variable scope for effective code organization and data management in Python.
Code snippets and programs related to Variable Scopes in Python, can be accessed from GitHub Repository. This GitHub repository all contains programs related to other topics in Python tutorial.
Interview Questions & Answers
What is the LEGB rule in Python?
LEGB rule is the order in which Python looks for a variables based on their scope. LEGB stands for:
- Local – Local scope is the innermost scope, i.e., within the current function or code block.
- Enclosing – This is the scope of any enclosing functions, in case of nested functions.
- Global – Module-level scope or global scope
- Built-in – The outermost scope, containing built-in names and functions.
In Python, reference to a variable is defined based on the LEGB order. Python will search these scopes in the LEGB order and will assign the first occurrence it finds.
What happens if we modify a global variable without the global keyword inside a function?
If we modify a global variable inside a function without using the global keyword, Python will consider it as a local variable within that function. This can lead to an error if the variable hasn’t been initialized within the function.
x = 10 # variable defined at module level but not marked global
def modify_variable():
x = 20 # This will create a new local variable 'x'
print(x) # This will print the value of local variable 'x'
modify_variable() # Output: 20, from local variable 'x'
print(x) # Output: 10 (module level variable 'x' is unchanged)
Give a scenario where nonlocal is necessary?
nonlocal is necessary when you have a nested function and you want to modify a variable from the enclosing function (not the global scope).
def counter():
count = 0 # Variable count is in the enclosing scope
def increment():
nonlocal count # With nonlocal, it is using the variable from enclosing scope
count += 1 # increase the value of enclosing scope variable count
return count
return increment
counter_function = counter() # This will return the increment() function assigned to variable counter_function
print(counter_function()) # call to increment() function, Output: 1, initially count was 0
print(counter_function()) # call to increment() function, Output: 2, count was 1 after previous increment
What will happen if global keyword is used inside a function for a variable that is not defined in the global scope?
If global keyword is used for a variable that hasn’t been defined globally (or at module level with global keyword), Python will create that variable in the global scope. Python won’t raise an error.
We need to be very careful, while defining a global variable from inside the function is very risky and can lead to unexpected behavior in your code. Also use the proper comments in code for this usage of global keyword.
def create_global():
global x # variable x defined in function but with global keyword
x = 100 # Assigns value to a global variable 'x'
create_global()
print(x) # Output: 100 from the global variable 'x'
How do Python closures relate to variable scope?
A closure in Python occurs when a nested function remembers the environment in which it was created, including variables from the enclosing scope, even after the outer function has finished executing. This is closely related to variable scope because closures allow the nested function to access variables from its enclosing scope, demonstrating the importance of the enclosing scope in the LEGB rule.
def outer_function(msg):
def inner_function():
print(msg) # 'msg' is from the enclosing scope
return inner_function
closure_function = outer_function("Hello, World!")
closure_function() # Output: Hello, World!
In this example program, outer_function(msg) returns an object of inner_function which prints the value of argument msg. We called the outer_function("Hello, World!"). msg is remembered by inner_function even after outer_function has finished executing. This is because of closure.
Test Your Knowledge: Practice Quiz
Related Topics
- Introduction to Variables in Python & Variable Data TypesWhat are Variables in Python In Python, variables act as references to reserved memory locations where actual values are stored. Each variable name points to a specific memory address that holds the assigned value. In this case: How Variable Memory Works When we define variables, like height = 175, Python allocates a specific memory location…
- Understanding Number Datatype in Python: Decimal, Octal and Hexadecimal NumbersUnderstanding the Number Datatype in Python: A Comprehensive Overview Number datatype in Python is a combination of different number format classes like Integer, Float, and Complex. Python supports the Decimal, Octal decimal, and Hexadecimal number systems. Program – Integer Number datatype Output of the Integer Number datatype program: Note from the output: Exploring Float Number…
- Understanding Scope in Python Programming (with Example Programs)In previous articles, we learned about following topics: Understanding Scope in Programming Generally, in the scope of a program, a variable can be declared only once with the same name. But, it’s possible to declare variables with the same name in different scopes within the same program. Changing the value of a variable within a…
- Understanding Lists in Python: A Comprehensive GuideLists in Python List is a core datatype in Python. Lists are sequences used to store elements (collection of data). Lists are similar to Arrays but are of dynamic size. It means the size of the list can be increased or decreased as we add or remove elements from the list. Understanding Python Lists: A…
- How to Create List in Python | Python List Creation Methods ExplainedList is a sequence data type used to store elements (collection of data). Lists are similar to Arrays but have a dynamic size, meaning the list size can increase or decrease as elements are added or removed. A list is a core data type in Python, along with Tuple, Set and Dictionary. Lists in Python…