1
test=4
def sum1(var):
    print("in function, test",test) 
    var+=1
    test=7
    print("in function, var",var)
    print("in function, test",test)  
sum1(5)
print(test)

I'm trying to understand global and local variable, so I try it this way: a global and a local variable that has same names (I know we normally don't do that).

In this program it has an "UnboundLocalError: local variable 'test' referenced before assignment" I am wondering why the first print() that prints the test cannot be printed out? Why wouldn't it call the global "test"?

ANEN
  • 11
  • 1
  • [9.2. Python Scopes and Namespaces](https://docs.python.org/3/tutorial/classes.html#python-scopes-and-namespaces) (in the Tutorial) [4.2. Naming and binding](https://docs.python.org/3/reference/executionmodel.html#naming-and-binding) (in the language reference) – wwii Nov 06 '22 at 21:01
  • The assignment `test=7` **in** the function makes `test` local to the function and the interpreter knows that the assignment happens after the print so it is complaining. The interpreter knows this because it has already done some *processing* of `sum1` - it has made a function object of it and the assignment causes an *entry* in its locals dictionary but it doesn't have anything assigned to it yet. If you comment out `test=7` it should run. – wwii Nov 06 '22 at 21:09
  • There are a lot of good answers in that duplicate other than the accepted one. It would be worthwhile reading some of those also. – wwii Nov 06 '22 at 21:13
  • I misspoke, `test` is not in the locals dictionary until the assignment but the *function* knows about it; add `print(sum1.__code__.co_varnames)` as the first statement in the function. – wwii Nov 06 '22 at 21:19

1 Answers1

0

Because your local test shadows the name of the global test, it's unclear to which one you're referring. If you comment out the line test = 7 in your function, you won't get the error, as python assumes you're referring to the global test.

If you insist on using var names in your local scope that shadow global vars (and you've just discovered why that's a very bad idea), you can be explicit about it:

def sum1(var):
    global test
    print("in function, test", test)
    ...

Now, however, when you get to test = 7, you're modifying the global test var. That's probably not what you wanted.

Danielle M.
  • 3,607
  • 1
  • 14
  • 31
  • `global test` isn't "be[ing] explicit about" "using var names in your local scope that shadow global vars"; it's just using the global variable. Actually reaching around a local would require something like `globals()["var"]`. – Davis Herring Nov 06 '22 at 21:05