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:
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 = 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
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.
Happy Learning 🙂