1

So I was writing some conditionals when I started facing this issue. Can someone please explain to me why this code fails to execute? (I simplified the semantics to make it simpler to reproduce)

a = 1
b = 2

def run():
  if a < b:
    a = b

run()

It raises an UnboundLocalError: local variable 'a' referenced before assignment. It seems to happen to the variable being assigned inside the if block so I changed the function to this:

def run():
  if a < b:
    b = a

And then the message was UnboundLocalError: local variable 'b' referenced before assignment.

I am not sure if this is due to scoping but this code works normally:

def run():
  print(a)
  print(b)

Is there any think I missed from how Python works? If so, sorry for the dumb question but I have been working with Python for more than 4 years and never saw this before.

Tested in Python 2.7.15rc1 inside WSL and Python 3.6.4 in Windows.

maikel
  • 44
  • 1
  • 7

2 Answers2

1

You might miss the knowledge of scope of variables.

# Here is the global scope of module

def func():
    # Here is the local scope of function

So in your code, to use the variable declared in global scope in local scope, you need to add global before calling them under local scope.

a = 1
b = 2

def run():
  global a
  if a < b:
    a = b

run()

Without the declare the global variable inside local scope, the exception UnboundLocalError will appear because you declare another local a in a line after comparison: if a < b. The syntax check will verify the variable declaration in local scope before the executing the code. Therefore, b doesn't need to be global inside local scope, but a needs.

Or another way is using globals() to call module lever variables. But this way will not change the value of variable in global scope.

a = 1
b = 2

def run():
  if globals()['a'] < b:
    a = b  # local scope a = 2

run()
# global scope a = 1
Kir Chou
  • 2,980
  • 1
  • 36
  • 48
0

If you want the a and b inside the function refer to the variables defined outside the function, you can do this:

a = 1
b = 2

def run():
    global a
    global b
    if a < b:
        a = b

run()
John Anderson
  • 35,991
  • 4
  • 13
  • 36