Python - Scope Of A Variable

Since this is a programming topic, let’s start with a code.

x = "Global Scope"
print(x)

Output

Global Scope

Alright, I guess it’s time to introduce Python Scopes, There are 4 scopes in Python:
LEGB - Local, Enclosing, Global, Built-in

Wait, What do you mean by scope?

Googling for scope will give you this definition:

scope
/skəʊp/
the extent of the area or subject matter that something deals with or to which it is relevant.
“we widened the scope of our investigation”
synonyms: extent, range, breadth, width, reach, sweep, purview, span, stretch, spread, horizon…

Well, that doesn’t help much but it will certainly help you to comprehend the definition of scope below:

A Scope in programming refers to the region of the code from which a variable or a method can be accessed.

Earlier, we wrote a code that stores the string Global Scope to a variable named x and printed it.

The variable x was in the Global Scope. And we were able to print the variable’s value because we were trying to access it from the same scope.

But how do we know whether the variable was in Global Scope?

In Python, every variable you define without any indentation is actually in Global Scope. However, that’s only the G part of LEGB, so now let’s move on to discussing the Local Scope.

Again, let’s do that with code.

x = "Global Scope"

def function():
    y = "Local Scope"
    print(y)

print(y)

Output

NameError: name 'y' is not defined

Oops! We got NameError: name 'y' is not defined. But Why?

It seems like our friend Global Scope doesn’t have access to internal matters. Variables defined in a function, class or a method (inner scope) can only be accessed within it. Consider it restricted territory.

16%20PM

The variable y is defined inside the function, that is in a Local Scope. Local Scope variables can only be accessed within the Local Scope. The Global Scope only knows that we have defined a function named function. It doesn’t know what’s inside the function. The only way for us to get the value inside the Local Scope is to execute the function. So let’s do that:

x = "Global Scope"

def function():
    y = "Local Scope"
    print(y)

function()

Output

Local Scope

As expected, as we executed the function, print(y) was able to access the y variable because it was in the same scope as the variable y. That is the Local Scope.

Okay, we still have 2 types of scopes remaining: Enclosing and Built-in. Since Enclosing Scope is just an extension of the Local Scope, let’s discuss that first.

x = "Global Scope"

def outer_func():
    y = "Enclosing Scope"
    
    def inner_func():
        z = "Local Scope"
        print(z)
    
    print(y)

If you consider Global Scope to be the outermost scope and Local Scope to be the innermost scope, then Enclosing Scope is the scope between those two. That is a scope that is neither Local nor Global. This kind of scope can be easily visualized when we create a function inside another function.

Note: Neither Global Scope is the outermost scope, nor Local Scope is the innermost scope. The Local Scope depends on the region of code we are talking about.

For example:

If we are talking about the function outer_func, then:

  • y belongs to Local Scope
  • x belongs to Global Scope

If we are talking about the function inner_func, then:

  • z belongs to Local Scope
  • y belongs to Enclosing Scope
  • x belongs to Global Scope

Now you might be curious, why isn’t Global Scope the outermost scope? It’s because Built-in Scope is the outermost scope. The Built-in scope contains predefined functions and objects like print(), min(), etc. We don’t have to define it in the Global Scope, because those functions are already defined in the Built-in Scope.

Now that we have discussed all 4 scopes. Let’s dive into how Python interpreter looks for variables and functions in each scope.

What was the logic behind writing the abbreviation LEGB? Python Interpreter always searches for the variable in LEGB order. That is, it first checks:

  1. Local Scope
  2. Enclosing Scope
  3. Global Scope
  4. Built-in Scope

This is why we cannot access a variable in the inner scope from the outer scope.

48%20PM

The above code will get executed in the following order:

Disclaimer: This conversation is for explanation purposes, this has no relation with reality.

Interpreter: I am going to execute the code in the Global Scope. But where is the definition of outer_func()?
System: It’s in the Global Scope
Interpreter: Awesome! It’s in the same scope, I am going to execute it. Hey, Where is the definition of inner_func()?
System: It’s in the Enclosing Scope.
Interpreter: Okay, So am inside the inner_func now. Where is the function Definition of print()? I couldn’t find it in the Local Scope.
System: Check Enclosing Scope.
Interpreter: Nope! Not there!
System: What about Global Scope?
Interpreter: Nope!
System: Sigh! Well, The only remaining scope is the Built-in Scope, Check there.
Interpreter: Aha! Got it. Okay, But where is x?
System: It’s in the Local Scope.
Interpreter: Found it. Printing its value.
System: Perfect! Great Job! :expressionless:

Since now we have an idea of how Python Interpreter looks for the variable or function, let’s remove the x from each inner scope to have a thorough understanding of this topic.

x = "Global Scope"

def outer_func():
    x = "Enclosing Scope"
    
    def inner_func():
        x = "Local Scope"
        print("I found x in", x)
    
    inner_func()
    
outer_func()

Output

I found x in Local Scope
x = "Global Scope"

def outer_func():
    x = "Enclosing Scope"
    
    def inner_func():
        print("I found x in", x)
    
    inner_func()
    
outer_func()

Output

I found x in Enclosing Scope
x = "Global Scope"

def outer_func():
    
    def inner_func():
        print("I found x in", x)
    
    inner_func()
    
outer_func()

Output

I found x in Global Scope

I hope this has helped you understand the scope of a variable in Python!

3 Likes

Great explanation, thanks a lot for sharing!

1 Like