[Solved-4 Solutions] Python variable scope error



Error Description:

  • The following code works as expected in both Python 2.5 and 3.0:
a, b, c = (1, 2, 3)
print(a, b, c)

def test():
    print(a)
    print(b)
    print(c)    # (A)
    #c+=1       # (B)
test() 
click below button to copy the code. By - python tutorial - team
  • However, when we uncomment line (B), we get an UnboundLocalError : 'c' not assigned at line (A). The values of a and b are printed correctly. This can raise up two questions:
    • Why is there a runtime error thrown at line (A) because of a later statement on line (B)?
    • Why are variables a and b printed as expected, while c raises an error?

Solution 1:

global c
click below button to copy the code. By - python tutorial - team
  • as the first line of the function.
  • As for python 3, there is now
nonlocal c 
click below button to copy the code. By - python tutorial - team
  • That you can use to refer to the nearest enclosing function scope that has a c variable.

Solution 2:

def test():
    global c
    print(a)
    print(b)
    print(c)    # (A)
    c+=1        # (B) 
click below button to copy the code. By - python tutorial - team
  • Also, the reason you are getting this error is because you can also declare a new variable inside that function with the same name as a 'global' one, and it would be completely separate.
  • The interpreter thinks you are trying to make a new variable in this scope called c and modify it all in one operation, which isn't allowed in Python because this new c wasn't initialized.

Solution 3:

bar = 42
def foo():
    print bar
    if False:
        bar = 0 
click below button to copy the code. By - python tutorial - team

Solution 4:

  • This is not a direct answer to your question, but it is closely related, as it's another gotcha caused by the relationship between augmented assignment and function scopes.
  • In most cases, you tend to think of augmented assignment (a += b) as exactly equivalent to simple assignment (a = a + b). It is possible to get into some trouble with this though, in one corner case. Let me explain:
  • The way Python's simple assignment works means that if a is passed into a function (like func(a) ; note that Python is always pass-by-reference), then a = a + b will not modify the athat is passed in. Instead, it will just modify the local pointer to a.
  • But if you use a += b, then it is sometimes implemented as:
a = a + b 
click below button to copy the code. By - python tutorial - team
a.__iadd__(b) 
click below button to copy the code. By - python tutorial - team
  • In the first case (as long as a is not declared global), there are no side-effects outside local scope, as the assignment to a is just a pointer update.
  • In the second case, a will actually modify itself, so all references to a will point to the modified version. This is demonstrated by the following code:
def copy_on_write(a):
      a = a + a
def inplace_add(a):
      a += a
a = [1]
copy_on_write(a)
print a # [1]
inplace_add(a)
print a # [1, 1]
b = 1
copy_on_write(b)
print b # [1]
inplace_add(b)
print b # 1 
click below button to copy the code. By - python tutorial - team
  • So the trick is to avoid augmented assignment on function arguments (I try to only use it for local/loop variables). Use simple assignment, and you will be safe from ambiguous behaviour.

Related Searches to Python variable scope error