Variable Scope in Python

Paul Livesey
3 min readDec 14, 2022

--

Local Scope

A variable is a local variable when it is inside of a function, like:

def funky():
x = 42
print(f'{x=}')

Here, the variable x is only available with the function. It only exists between the definition of funky() and the end of the function. If you try and access it outside, like this:

def funky():
x = 42
print(f'{x=}')
funky()
print(f'{x=}')

You get a horrible error:

x=42
Traceback (most recent call last):
File "/Users/poblivsig/temp/Scrape/123.py", line 6, in <module>
print(f'{x=}')
NameError: name 'x' is not defined

Python is basically saying, ‘What the hell is x???’. That is because it doesn’t exist.

Global Scope

If you declare a variable outside of a function, it is created as a global variable and may be accessed inside and outside functions:

x = 123
def funky():
print(f'Inside function, {x=}')
funky()
print(f'Outside function, {x=}')

Output:

Inside function, x=123
Outside function, x=123

N.B. Using an equals sign inside of an f-string like this will print the name of the variable and it’s value in a format as seen in the output above.

Check out the IDs of the x inside and outside the funky() function:

x = 123
def funky():
global x
print(f'Inside function, {id(x)=}')
funky()
print(f'Outside function, {id(x)=}')

Output:

Inside function, id(x)=4529031328
Outside function, id(x)=4529031328

They are the same! The variable is not really a variable in the traditional C-style sense of the word. It is really an object with a symbolic name that points to the object. What has that got to do with any of this?

Notice that we are only examining variables, we are not altering them in any way. Well, let’s try and alter x inside the function:

x = 123
def funky():
x = 42
print(f'Inside function, {x=}')
print(f'Inside function, {id(x)=}')

funky()
print(f'Outside function, {x=}')
print(f'Outside function, {id(x)=}')

Output:

Inside function, x=42
Inside function, id(x)=4513459840
Outside function, x=123
Outside function, id(x)=4513462432

Can you guess what is happening here? Have a think about it before reading the answer.

What is happening is that when we are setting what we think is the global variable x inside of the function, what we are actually doing is creating a completely different variable (or object) that has local scope. That is why they have different IDs.

To fix this problem, we need to use the global keyboard like this:

x = 123
def funky():
global x
x = 42
print(f'Inside function, {x=}')
print(f'Inside function, {id(x)=}')

funky()
print(f'Outside function, {x=}')
print(f'Outside function, {id(x)=}')

Output:

Inside function, x=42
Inside function, id(x)=4409880192
Outside function, x=42
Outside function, id(x)=4409880192

That sorted it. We can now see that the IDs are the same. Our symbolic name is the same. It points to the same object inside and outside the functions. One little thing to watch out for is something like this:

def funky():
x = 42
print(f'Inside function, {x=}')
global x
print(f'Inside function, {id(x)=}')

When we try to compile this we get an error:

File "/Users/poblivsig/temp/Scrape/123.py", line 6
global x
^
SyntaxError: name 'x' is used prior to global declaration

Make sure you use the global keyword before you use x. This is the result of using global after using it. You are creating x as a local and then again as a global. Python is very confusing!

Functions in Functions Scope

This kind of scope is useful for what is known as closures, amongst other things. When you create a function inside of another function, the inner function has access to the variables in the outer function:

def funky():
x = 42
def funkster():
print(f'{x=}')
funkster()

funky()

This may have freaked you out a little if you have never seen this kind of thing before. What is basically happening is that when we have a function inside of another function, the inside function has access to the identifiers in the outside function. Why would you need this? I am afraid that this is outside the scope of this article. I do recommend Python Tricks: A Buffet of Awesome Python Features: Bader, Dan for this kind of thing (and lots of other interesting, advanced Python fun). I am not affiliated with this in any way and I don’t make any cash. I just love the book. If you don’t want to spend money, just look up Python closures (amongst other things).

--

--

Paul Livesey

I am a teacher of Computer Science, currently living in China. At the same time I am trying to complete a Masters at Georgia Tech in Machine Learning.