When working with any programming language, the variables and objects that we’re working with are only accessible within certain scopes. In this tutorial, we’ll take a closer look at how scopes work and when our variables might not be what we expect them to be.

What is a Scope in Python?

When we say that we’re working in a different scope in Python, we mean that we’re within the boundaries of a function or a class. This is important because while within the body of a function or class, the variables that we create are not automatically accessible outside of that context.

Let’s create a new file called scopes.py so that we can experiment with how scopes work. To start, let’s see how variables work when dealing with conditionals and loops.

scopes.py
if 1 < 2:
    x = 5
while x < 6:
    print(x)
    x += 1
print(x)

Here we’re creating a variable (x=5) within the body of a conditional (if 1 < 2:1). Afterward, we attempt to access that variable within the context of a loop (while x < 6:) and at the highest level of our script. Will this work? Let’s find out by running this through the interpreter:

Terninal
5
6

We didn’t run into an error because conditionals and loops do not create scopes. Now, let’s change our conditional to be a function instead.

scopes.py
def set_x():
    x = 5

set_x()

while x < 6:
    print(x)
    x += 1

print(x)

Now if we run this we’ll see the following:

Terminal
Traceback (most recent call last):
File "scopes.py", line 7, in <module>
while x < 6:
NameError: name 'x' is not defined

We see this error because x is defined within the set_x function and only exists during the execution of the function.

Name Hiding (Shadowing):

Now that we’ve looked at how scopes work initially, we’re ready to look at what happens when we have a function parameter that is the same as a variable that exists at a higher level. This is sometimes called shadowing or name hiding.

We know that functions create scopes. But, what happens when a parameter name is the same as a variable that has already been defined?

Let’s continue using scopes.py to see what happens when we set y before we define the set_x function, and then change our function to have a y parameter.

scopes.py
y = 5

def set_x(y):
    print("Inner y:", y)
    x = y
    y = x

set_x(10)
print("Outer y:", y)

Now if we run this, we’ll see the following:

Terminal
Inner y: 10
Outer y: 5

Since our function defines the y parameter, it’s as though the outer y variable doesn’t exist within the set_x function.

Name hiding makes it possible for us to be confident that our parameters won’t be affected by values at a higher scope. That doesn’t mean that name hiding is something that we should always use though because it can make our code a little harder for people to understand.

References:

Happy Learning 🙂