Scopes in Python

Posted by Daksh on Sunday, April 3, 2022

Scopes in Python

The scope of a variable is the part of the program where a variable is accessible. The purpose of a scope is to protect the variable by limiting its accessiblity. The way scoping works is that the innermost function has access to almost everything available outside.

Built-in Scopes covers all the language of Python, such as reserved keywords like def, class, if, else, for, while, etc and therefore, you can access it from the outermost scopes or the innermost scopes in the function classes. Global Scopes are the variables defined outside of a function. Enclosing scope refers to a function inside another function or what is commonly called a nested function. Local scope refers to a variable declared inside a function.

The variable will always be accessible at the level of its declaration. Moreover, Global variables are accessible globally, enclosedly and locally. Enclosed variables are accessible enclosedly and locally. Local variables are only accessible locally. Functions with built-in scope can be accessed at any level.

In Python, there are 4 types of scopes (refered as LEGB):

  • Local Scope
  • Enclosing Scope
  • Global Scope
  • Built-in Scope
# Global Scope
global_var = 2

# Built-in Scope (def)
def outer():
    # Enclosing Scope
    enclosing_var = 4   
    def inner():
        # Local Scope
        local_var = 10
        print(x)

Global Scope is generally discouraged because of the possibility of making mistakes.

Let’s take a look at some examples

Case of a for loop. Sometimes, we unknowingly ignore the fact that the iterator variable can be accessed outside the loop.

for i in range(5):
    print(i)

print(f"'i' is still accessible outside the loop, and its value is {i}")


# Output:
# 0
# 1
# 2
# 3
# 4
# 'i' is still accessible outside the loop, and its value is 4

Case of a while loop.


i = 0
while i < 5:
    print(i)
    i += 1

print(f"'i' is accessible outside the loop, and its value is {i}")

# Output:
# 0
# 1
# 2
# 3
# 4
# 'i' is accessible outside the loop, and its value is 5

Case of a generator.

def generator():
    for i in range(5):
        yield i

# print(f"'i' is not accessible outside the function, and its value is {i}") 
# NameError: name 'i' is not defined

for i in generator():
    print(i)

print(f"'i' is accessible outside the loop, and its value is {i}")

# Output:
# 0
# 1
# 2
# 3
# 4
# 'i' is accessible outside the loop, and its value is 4

Case of a list comprehension.

result = sum(v for v in range(1, 30) if v % 3 == 0 or v % 5 == 0)

print(v)

# Output:
# Traceback (most recent call last):
# NameError: name 'v' is not defined

Iterating over a list.

for num in [1, 2, 3, 4, 5]:
    print(num)

print(f"'num' is accessible outside the loop, and its value is {num}")

# Output:
# 1
# 2
# 3
# 4
# 5
# 'num' is accessible outside the loop, and its value is 5

Be careful with these scopes or keep debugging to find out the cause of the error :)