Local and Global Variable Lookup Weirdness in Python

mCoding · Intermediate ·🌐 Frontend Engineering ·5y ago

Key Takeaways

The video discusses variable lookup rules in Python, specifically how local and global variables are handled, and how assignments later in a function can affect earlier statements.

Full Transcript

hello and welcome i'm james murphy and today we're taking a look at a subtle rule that python has about variable scopes let's play a game what does the function print let's start with an easy one shout out the answers as we go tell me either what it's going to print or what error it's going to give let's start with f what do you think happens when we run it well of course when we run it we get an error specifically a name error okay the first one was really easy what about the second one g is it any different from f well of course we still get an error but it's actually a different error now technically unbound local error derives from name error but i think it might be surprising to many of you that something different happened at all somehow python knew that i was going to assign to x later in the function normally in python outside of a looping context we don't expect statements in a function that are later in the function to affect statements that are earlier in the function it turns out that whether or not a variable like x is determined to be a free variable or a local variable is actually determined at compile time not at runtime in the function f there are no assignments to the variable x so x is determined to be a free variable that means when we say print x it tries to look up x in the global scope and fails in g however the function does contain an assignment for x it says x equals 1. so that means that in the function g x is determined to be a local variable that means that when we try to print x it looks it up in the local scope and hence we get a local error not a global error keeping that in mind let's look at another two examples and see if you get them right what do you think happens when we call h we have defined the global variable y equals 0 before defining the function and then we try to print y in the function go on just shout it out okay this was another easy one it prints zero now what do you think happens for the j function take your time i'll wait okay have you locked your guess in here we go when i run the j function i get another unbound local error now you might look at this and say when i call j we have this global variable y that's defined to be zero so print y should be printing 0 just like in the previous case but that's not how the variable lookup rules work because somewhere in the function j assigns y a value everywhere in the function y is treated as a local variable that means at the beginning when we try to print y it doesn't even try to look it up in the global scope it only looks in the local scope this can be extra confusing because this assignment y equals 1 could theoretically be hundreds of lines later in the function this is yet another reason to avoid using global variables if you can i also want to point out that other languages like c and c plus do not do things this way when i run this function it first prints the global i and then prints the local i that's why we get 0 and then 1 down at the bottom here i even compile with wall and w extra to give me extra warnings and still no warnings to be seen if i want to get a warning for this kind of behavior i have to compile with w shadow the shadow here is referring to the fact that what i'm doing is called variable shadowing if i have a variable and an inner scope like inside a function where i define a variable that has the same name as another variable in an outer scope like the global scope then this is called variable shadowing in this case i would say that this variable i shadows the one in the global scope for obvious reasons you should really try to avoid this if at all possible of course the same goes for python shadowing variables puts you on the fast track to writing bugs in case you were ever wondering this is actually one of the reasons why i define a separate main function rather than just putting things down here any assignments that i do down here are actually in the global scope and that means there's a chance that they're being shadowed i might expect an error if i try to print y here but because the y down here is in the global scope i actually just print that y instead on the other hand if i define a main function then any assignments in here that i do are local to that function that means anything that i do in here i don't have to worry about affecting things in other functions like h now when i run the function i get the expected error in h that's all i've got on this topic now that you know the rules go back and watch the video again and let me know if you get them all right this time if you like the video please consider sharing with your friends subscribing and slapping that like button an odd number of times you

Original Description

Variable lookup rules in Python are weird! Did you know that a statement in a function can be affected by a LATER assignment? This is a subtle rule of variable lookup in Python. ― mCoding with James Murphy (https://mcoding.io) Source code: https://github.com/mCodingLLC/VideosSampleCode Python docs: https://docs.python.org/3/reference/executionmodel.html SUPPORT ME ⭐ --------------------------------------------------- Patreon: https://patreon.com/mCoding Paypal: https://www.paypal.com/donate/?hosted_button_id=VJY5SLZ8BJHEE Other donations: https://mcoding.io/donate BE ACTIVE IN MY COMMUNITY 😄 --------------------------------------------------- Discord: https://discord.gg/Ye9yJtZQuN Github: https://github.com/mCodingLLC/ Reddit: https://www.reddit.com/r/mCoding/ Facebook: https://www.facebook.com/james.mcoding
Watch on YouTube ↗ (saves to browser)
Sign in to unlock AI tutor explanation · ⚡30

Playlist

Uploads from mCoding · mCoding · 24 of 60

1 Goodbye, List! Type hinting standard collections - New in Python 3.9
Goodbye, List! Type hinting standard collections - New in Python 3.9
mCoding
2 Python's comma equals ,= operator?
Python's comma equals ,= operator?
mCoding
3 Finding Primes in Python with the Sieve of Eratosthenes
Finding Primes in Python with the Sieve of Eratosthenes
mCoding
4 Find the First Missing Positive Int | Hard Interview Question on LeetCode
Find the First Missing Positive Int | Hard Interview Question on LeetCode
mCoding
5 JSON Tutorial Python | Basic Python Recipes
JSON Tutorial Python | Basic Python Recipes
mCoding
6 Simulating Brownian Motion in Python
Simulating Brownian Motion in Python
mCoding
7 The Single Most Useful Decorator in Python
The Single Most Useful Decorator in Python
mCoding
8 The Fastest Way to Loop in Python - An Unfortunate Truth
The Fastest Way to Loop in Python - An Unfortunate Truth
mCoding
9 Numpy Array Broadcasting In Python Explained
Numpy Array Broadcasting In Python Explained
mCoding
10 Brownian Motion Single Path Zoom
Brownian Motion Single Path Zoom
mCoding
11 Brownian Motion Fractal Zoom
Brownian Motion Fractal Zoom
mCoding
12 Magic Methods - Making Python builtins work with your classes
Magic Methods - Making Python builtins work with your classes
mCoding
13 50 Million Primes In 5 Seconds - Segmented Sieve of Eratosthenes
50 Million Primes In 5 Seconds - Segmented Sieve of Eratosthenes
mCoding
14 The Hottest New Feature Coming In Python 3.10 - Structural Pattern Matching / Match Statement
The Hottest New Feature Coming In Python 3.10 - Structural Pattern Matching / Match Statement
mCoding
15 How Fast is Python's Sort? Performance Testing
How Fast is Python's Sort? Performance Testing
mCoding
16 C++ First Missing Int, faster than 100%!
C++ First Missing Int, faster than 100%!
mCoding
17 [April Fools 2021] Python 4.0! New old print, mandatory static typing, StackOverflow integration
[April Fools 2021] Python 4.0! New old print, mandatory static typing, StackOverflow integration
mCoding
18 Python dataclasses will save you HOURS, also featuring attrs
Python dataclasses will save you HOURS, also featuring attrs
mCoding
19 C++ Sudoku Solver in 7 minutes using Recursive Backtracking
C++ Sudoku Solver in 7 minutes using Recursive Backtracking
mCoding
20 Every PROOF you've seen that .999... = 1 is WRONG
Every PROOF you've seen that .999... = 1 is WRONG
mCoding
21 Python's sharpest corner is ... plus equals? (+=)
Python's sharpest corner is ... plus equals? (+=)
mCoding
22 Binary Search - A Different Perspective | Python Algorithms
Binary Search - A Different Perspective | Python Algorithms
mCoding
23 The Best Way to Check for Optional Arguments in Python
The Best Way to Check for Optional Arguments in Python
mCoding
Local and Global Variable Lookup Weirdness in Python
Local and Global Variable Lookup Weirdness in Python
mCoding
25 Efficient Exponentiation
Efficient Exponentiation
mCoding
26 How To Install Python for Data Science
How To Install Python for Data Science
mCoding
27 0.1 + 0.2 is NOT 0.3 in Most Programming Languages
0.1 + 0.2 is NOT 0.3 in Most Programming Languages
mCoding
28 Python 3.10's new type hinting features
Python 3.10's new type hinting features
mCoding
29 Python 3.10's Quality of Life improvements
Python 3.10's Quality of Life improvements
mCoding
30 Introducing mZips! Python Zip and Zip Longest
Introducing mZips! Python Zip and Zip Longest
mCoding
31 Match statement tips
Match statement tips
mCoding
32 Using except: is a HUGE mistake
Using except: is a HUGE mistake
mCoding
33 Python + YouTube API | Automating descriptions
Python + YouTube API | Automating descriptions
mCoding
34 Anaphones, phonetic anagrams
Anaphones, phonetic anagrams
mCoding
35 Cracking passwords using ONLY response times | Secure Python
Cracking passwords using ONLY response times | Secure Python
mCoding
36 Python f-strings can do more than you thought. f'{val=}', f'{val!r}', f'{dt:%Y-%m-%d}'
Python f-strings can do more than you thought. f'{val=}', f'{val!r}', f'{dt:%Y-%m-%d}'
mCoding
37 Diagnose slow Python code. (Feat. async/await)
Diagnose slow Python code. (Feat. async/await)
mCoding
38 Python MD5 implementation
Python MD5 implementation
mCoding
39 Salting, peppering, and hashing passwords
Salting, peppering, and hashing passwords
mCoding
40 x to bool conversion in Python, C++, and C
x to bool conversion in Python, C++, and C
mCoding
41 You should put this in all your Python scripts | if __name__ == '__main__': ...
You should put this in all your Python scripts | if __name__ == '__main__': ...
mCoding
42 Find the Skyline Problem with C++ Solution Explained
Find the Skyline Problem with C++ Solution Explained
mCoding
43 The ONLY C keyword with no C++ equivalent
The ONLY C keyword with no C++ equivalent
mCoding
44 Should you use "not not x" instead of "bool(x)" in Python? (NO!)
Should you use "not not x" instead of "bool(x)" in Python? (NO!)
mCoding
45 Multiple Assignments in Python
Multiple Assignments in Python
mCoding
46 Why I don't like Python's chained comparisons
Why I don't like Python's chained comparisons
mCoding
47 Automated Testing in Python with pytest, tox, and GitHub Actions
Automated Testing in Python with pytest, tox, and GitHub Actions
mCoding
48 You can pip install directly from GitHub
You can pip install directly from GitHub
mCoding
49 __new__ vs __init__ in Python
__new__ vs __init__ in Python
mCoding
50 Metaclasses in Python
Metaclasses in Python
mCoding
51 The easy way to keep your repos tidy.
The easy way to keep your repos tidy.
mCoding
52 Which Python @dataclass is best? Feat. Pydantic, NamedTuple, attrs...
Which Python @dataclass is best? Feat. Pydantic, NamedTuple, attrs...
mCoding
53 Python __slots__ and object layout explained
Python __slots__ and object layout explained
mCoding
54 C++ cache locality and branch predictability
C++ cache locality and branch predictability
mCoding
55 Avoiding import loops in Python
Avoiding import loops in Python
mCoding
56 25 nooby Python habits you need to ditch
25 nooby Python habits you need to ditch
mCoding
57 Python staticmethod and classmethod
Python staticmethod and classmethod
mCoding
58 Building a Python app with Anvil to email me if my website goes down (includes paid features)
Building a Python app with Anvil to email me if my website goes down (includes paid features)
mCoding
59 31 nooby C++ habits you need to ditch
31 nooby C++ habits you need to ditch
mCoding
60 Interviewing the creator of C++, Bjarne Stroustrup
Interviewing the creator of C++, Bjarne Stroustrup
mCoding

The video teaches how Python's variable lookup rules work, including how local and global variables are handled, and how to avoid common pitfalls. Understanding these rules is crucial for writing effective and bug-free Python code.

Key Takeaways
  1. Define a function with a local variable
  2. Assign a value to the local variable later in the function
  3. Try to print the local variable before it's assigned
  4. Observe the UnboundLocalError
  5. Define a global variable and try to print it in a function
  6. Assign a value to the global variable in the function and observe the behavior
💡 In Python, whether a variable is local or global is determined at compile time, not runtime, which can lead to unexpected behavior if not understood properly.

Related Reads

📰
Next.js vs Remix vs SvelteKit: Which Framework Should You Learn?
Learn how to choose between Next.js, Remix, and SvelteKit for your next project and why it matters for your career as a developer
Dev.to · Etrit Neziri
📰
Had my Frontend Developer interview with Capgemini (Application Developer) today, and I wanted to…
Prepare for a frontend developer interview with Capgemini by reviewing JavaScript fundamentals and practicing common interview questions
Medium · JavaScript
📰
10 Frontend Developer Tools to Boost Productivity in 2026
Boost frontend productivity with 10 essential tools for modern web app development
Medium · Programming
📰
10 Frontend Developer Tools to Boost Productivity in 2026
Boost frontend productivity with top 10 developer tools in 2026
Medium · JavaScript
Up next
The masks we wear | Zora Krstić | TEDxLuxembourgCity
TEDx Talks
Watch →