Last updated: Apr 10, 2024
Reading timeยท6 min
The Python "UnboundLocalError: cannot access local variable 'X' where it is not associated with a value" occurs for multiple reasons:
try/except
statement.To solve the error, mark the variable as global
before referencing it in the
function or make sure to assign a value to the variable regardless if a
condition is met.
Here is an example of how the error occurs.
country = 'Austria' def my_func(): # โ๏ธ UnboundLocalError: cannot access local variable 'X' where it is not associated with a value print(country) country = 'Germany' my_func()
We reference the country
variable in the function before assigning a value to
it.
country
variable within the function makes it a local (to the function) variable and we try to access the variable before assigning a value to it.The local country
variable shadows the country
variable that is declared in
the global scope.
global
before accessing it within the functionTo solve the error, mark the variable as global before accessing it within your function.
country = 'Austria' def my_func(): # ๐๏ธ Mark as global first global country print(country) country = 'Germany' # ๐๏ธ Call function to reassign the variable my_func() # ๐๏ธ Austria # ๐๏ธ Now the `country` variable is set to `Germany` my_func() # ๐๏ธ Germany
global
.When we mark the variable as global
, we tell to the interpreter to look for it
in the global
scope.
The first call to the function reassigns the global country
variable, setting
it to "Germany".
Once we call the function the second time and print the country
variable, it's
already set to "Germany".
You can reference the country
global variable from within the function,
however, if you assign a value to the variable, the local variable shadows the
global one.
country = 'Austria' def my_func(): # ๐๏ธ Can access global variable here print(country) my_func() # ๐๏ธ Austria
If you assign a value to the variable within the function without marking it as
global
, the assignment only applies to the function's local scope.
country = 'Austria' def my_func(): # ๐๏ธ This only applies within the function country = 'Germany' print(country) print(country) # ๐๏ธ Austria my_func() # ๐๏ธ Germany print(country) # ๐๏ธ Austria
The country
variable in the function is set to 'Germany' and the country
variable outside the function has a value of 'Austria'.
This behavior is very confusing and should generally be avoided.
It is much better to pick different names and avoid clashes.
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.
def outer(): # ๐๏ธ Initialize country variable country = '' def inner(): # ๐๏ธ Mark country as nonlocal nonlocal country country = 'Germany' print(country) # ๐๏ธ Invoke inner function inner() print(country) # ๐๏ธ "Germany" outer()
The nonlocal
keyword allows us to work with the local variables of enclosing
functions.
country
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.
def outer(): # ๐๏ธ Initialize country variable country = '' def inner(): # ๐๏ธ Declares country in inner function's scope country = 'Germany' print(country) inner() # ๐๏ธ Refers to outer's country variable print(repr(country)) # ๐๏ธ "" outer()
If you get the error "Local variable referenced before assignment", check out the following article.
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.
country = 'Austria' def my_func(): print(country) # ๐๏ธ Austria new_country = 'Germany' return new_country result = my_func() print(result) # ๐๏ธ Germany country = result print(country) # ๐๏ธ Germany
We simply return the value that we eventually assign to the country
global
variable.
You should also consider passing the global variable as an argument to the function.
country = 'Austria' def my_func(ctry): location = 'Linz, ' + ctry return location result = my_func(country) print(result) # ๐๏ธ Linz, Austria
We passed the country
global variable as an argument to the function.
If we assign a value to a variable in a function, the variable is assumed to be
local unless explicitly declared as global
.
Another common cause of the error is assigning a value to a variable only if a condition is met and trying to access it after.
def my_func(): if 5 > 10: country = 'Germany' print(country) # โ๏ธ UnboundLocalError: cannot access local variable 'country' where it is not associated with a value return f'Country: {country}' my_func()
The if
statement checks if 5
is greater than 10
.
The condition is never met, so the country
variable never gets set.
When we try to access the variable after the if
block, we get the error
because the variable was never associated with a value.
To solve the error, set the variable to a default value before the if
block.
def my_func(): country = None if 5 > 10: country = 'Germany' print(country) return f'Country: {country}' print(my_func())
We initialized the country
variable to None
outside the if
block.
We used a default value of None
, but you can also use an empty string ""
or
0
as the default value, depending on your use case.
The variable is set even if the if
condition isn't met, so the error is never
raised.
try/except
statementAnother cause of the error is only assigning a value to a variable in a try/except statement.
def my_func(): try: raise ValueError('Something went wrong') country = 'Germany' print(country) except ValueError: pass # โ๏ธ UnboundLocalError: cannot access local variable 'country' where it is not associated with a value return f'Country: {country}' print(my_func())
Notice that an error is raised before the country
variable is declared in the
try
block.
The variable is never given a value, so when we try to access it in the
return statement, an
UnboundLocalError
occurs.
To solve the error, set the variable to an initial value before the try
statement.
def my_func(): country = None try: raise ValueError('Something went wrong') country = 'Germany' print(country) except ValueError: pass return f'Country: {country}' print(my_func()) # ๐๏ธ Country: None
We initialized the country
variable to None
before the try
block.
We used None
as the default value, but you can also set the variable to an
empty string ""
or 0
depending on your use case.
Even if an error is raised in the try
block, the variable is still associated
with a value because we've initialized it prior.
You can learn more about the related topics by checking out the following tutorials: