Last updated: Apr 8, 2024
Reading time ยท 4 min
The Python "UnboundLocalError: Local variable referenced before assignment" occurs when we reference a local variable before assigning a value to it in a function.
To solve the error, mark the variable as global in the function definition, e.g. global my_var .
Here is an example of how the error occurs.
Copied!name = 'Alice' def example(): # โ๏ธ UnboundLocalError: local variable 'name' referenced before assignment print(name) name = 'Bob' # ๐๏ธ This makes the variable local example()
We assign a value to the name variable in the function.
This makes the name variable local to the function and the local name variable shadows the one in the global scope.
To solve the error, mark the variable as global in your function definition.
Copied!name = 'Alice' def example(): # ๐๏ธ Mark global global name print(name) name = 'Bob' example() # ๐๏ธ 'Alice' example() # ๐๏ธ 'Bob'
If a variable is assigned a value in a function's body, it is a local variable unless explicitly declared as global .
You could reference the global name variable from inside the function but if you assign a value to the variable in the function's body, the local variable shadows the global one.
Copied!name = 'Alice' def example(): # โ This is ok print(name) example() # ๐๏ธ 'Alice'
Accessing the name variable in the function is perfectly fine.
On the other hand, variables declared in a function cannot be accessed from the global scope.
Copied!def example(): name = 'Bobby Hadz' example() # โ๏ธ Error print(name)
The name variable is declared in the function, so trying to access it from outside causes an error.
Make sure you don't try to access the variable before using the global keyword, otherwise, you'd get the SyntaxError: name 'X' is used prior to global declaration error.
An alternative solution to using the global keyword is to return a value from the function and use the value to reassign the global variable.
Copied!name = 'Alice' def example(): print(name) # ๐๏ธ 'Alice' new_name = 'Bob' return new_name result = example() print(result) # ๐๏ธ 'Bob' name = result print(name) # ๐๏ธ 'Bob'
We simply return the value that we eventually use to assign to the name global variable.
You should also consider passing the global variable as an argument to the function.
Copied!name = 'Alice' def example(first): full_name = first + ' Smith' return full_name result = example(name) print(result) # ๐๏ธ 'Alice Smith'
We passed the name global variable as an argument to the function.
When we assign a value to a variable in a scope, that variable becomes local to that scope and shadows variables with the same name in the outer scope.
If we assign a value to a variable in a function, the variable is assumed to be local unless explicitly declared as global .
If you have a nested function and are trying to assign a value to the local variables from the outer function, use the nonlocal keyword.
Copied!def outer(): # ๐๏ธ Initialize message variable message = '' def inner(): # ๐๏ธ Mark the message variable as nonlocal nonlocal message message = 'hello world' print(message) inner() print(message) # ๐๏ธ "hello world" outer()
The nonlocal keyword allows us to work with the local variables of enclosing functions.
Note that we had to initialize the message variable in the outer function, but we were able to change its value in the inner function.
Had we not used the nonlocal statement, the call to the print() function would have returned an empty string.
Copied!def outer(): # ๐๏ธ Initialize message variable message = '' def inner(): # ๐๏ธ Declares message in inner's scope message = 'hello world' print(message) inner() print(repr(message)) # ๐๏ธ "" outer()
Printing the message variable on the last line of the function shows an empty string because the inner() function has its own scope.
Changing the value of the variable in the inner scope is not possible unless we use the nonlocal keyword.
Instead, the message variable in the inner function simply shadows the variable with the same name from the outer scope.
As shown in this section of the documentation, when you assign a value to a variable inside a function, the variable:
The last line in the example function assigns a value to the name variable, marking it as a local variable and shadowing the name variable from the outer scope.
Copied!name = 'Alice' def example(): # โ๏ธ UnboundLocalError: local variable 'name' referenced before assignment print(name) name = 'Bob' # ๐๏ธ This makes the variable local example()
At the time the print(name) line runs, the name variable is not yet initialized, which causes the error.
The most intuitive way to solve the error is to use the global keyword.
Copied!name = 'Alice' def example(): # ๐๏ธ Mark as global global name print(name) name = 'Bob' example() # ๐๏ธ 'Alice' example() # ๐๏ธ 'Bob'
The global keyword is used to indicate to Python that we are actually modifying the value of the name variable from the outer scope.
If you want to read more about why this error occurs, check out [this section] (this section) of the docs.
You can learn more about the related topics by checking out the following tutorials:
I wrote a book in which I share everything I know about how to become a better, more efficient programmer.