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.
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:
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.
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:
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.
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:
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 🙂