Search code examples
pythonfunctionscopegloballocal-variables

Does python redefine guess of variable scope inside function?


I have a simple example that is confusing me, concerning local and global scopes in functions.

a=1
def func():
    print(a)   # Error: local variable 'a' referenced before assignment
    a=2
    print(a)

func()

If I comment the first print statement it runs fine. The local "a" takes precedence over the global "a" and hence 2nd print gives 2.

If I comment the a=2, then the print statements in the local scope see the global scope and print a=1.

What is confusing me is that when I run the entire function python throws an error: "local variable 'a' referenced before assignment"

What I was expecting was that the first print(a) produces 1 and the second print(a) produces 2.

I'm struggling to tease this apart. I examined locals() inside the func() so the first print function sees no local but it does see a global a. I'm really a bit lost and would appreciate someone explaining why it appears that the combination errors when the individual bits work fine.


Solution

  • When you make an assignment to a variable in a scope, it becomes local to that scope and shadows any similarly named variable in the outer scope. Since Python's scoping is static, wheter a is local or global is determined at compile time and that's why, when it comes to func(), Python sees a is assigned within the function body and treats it as a local variable throughout the entire function. Note at this point it's irrelevant where in the function body this happen exactly - it's sufficient for Python to just know it does. When you try to print(a) before local a has been really assigned a value within that function, you will face an error. When you comment out a = 2 however, then local a is gone, and Python sees one from global scope, therefore print(a) executes successfully as the a at that point is assigned a value.