I read the following in the Python documentation:
When a name is not found at all, a
NameErrorexception is raised. If the current scope is a function scope, and the name refers to a local variable that has not yet been bound to a value at the point where the name is used, an
UnboundLocalErrorexception is raised.
UnboundLocalErroris a subclass of
Python lacks declarations and allows name binding operations to occur anywhere within a code block.
I don’t understand how this works. If there are no declarations, then when does
UnboundLocalError get raised? How can the variable "not yet be bound" when it is encountered?
See also UnboundLocalError trying to use a variable (supposed to be global) that is (re)assigned (even after first use) for a common problem where a variable expected to be global, is local instead. This question is focused on cases where the programmer expects the variable to be local.
You can refer to a name without having assigned to it:
>>> foobar Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'foobar' is not defined
foobar is being referred to, but was never assigned to. This raises a
NameError because the name was never bound.
More subtly, here assignment is not happening because the line that does is never run:
>>> def foo(): ... if False: ... spam = 'eggs' ... print(spam) ... >>> foo() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 4, in foo UnboundLocalError: local variable 'spam' referenced before assignment
spam = 'eggs' is never executed,
print(spam) raises an
Note that nowhere in Python is a name ever declared. You bind or don’t bind, declaration is not part of the language.
Instead, binding is used to determine the scope of a name; binding operations include assignment, names used for a
for loop, function parameters, import statements, name to hold a caught exception in an
except clause, and the name for a context manager in a
If a name is bound in a scope (such as in a function) then it is a local name, unless you use a
global statement (or a
nonlocal statement in Python 3) to explicitly mark the name as a global (or a closure) instead.
So the following is an error:
>>> foo = None >>> def bar(): ... if False: ... foo = 'spam' ... print(foo) ... >>> bar() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 4, in bar UnboundLocalError: local variable 'foo' referenced before assignment
foo is being bound somewhere in the
bar function scope. But if you mark
foo as a global, the function works:
>>> foo = None >>> def bar(): ... global foo ... if False: ... foo = 'spam' ... print(foo) ... >>> bar() None
because now the Python compiler knows you wanted
foo to be a global instead.
This is all documented in the Naming and Binding section of the Python reference documentation.
One more place is when the variable is declared in global scope and if it is used in function scope, it should specifically refer as global otherwise UnboundLocalError occurs. Following is the example:
var = 123 def myfunc(): var = var + 1 print var myfunc()
UnboundLocalError: local variable 'var' referenced before assignment
UnboundLocalError is a special kind of
NameError, that specifically refers to local variables. The same kinds of logical problems that cause
NameErrors in code outside of functions, can cause
UnboundLocalError inside them.
Commonly, the problem occurs when trying to write conditional logic that doesn’t have any fallback:
import random def example_if(): if random.random() < 0.5: result = 1 return result print(example_if())
This will fail whenever the condition isn’t satisfied, because in that case there wasn’t anything assigned to
result, so there’s no way to use it. It’s important to understand here that there are no "default" values for variables, and that assigning
None to something is not the same as deleting the name with
(This could also be a symptom of a logical error with indentation: check whether the code using the variable is also supposed to be inside the
A sneaky variation on this is a loop that is supposed to assign the value, but runs zero times:
def example_for(): for i in range(0): # this loop will not be entered result = 1 # therefore this assignment will not happen return result print(example_for()))
In more practical examples, a
for loop might fail to run because it is iterating over results from a searching operation (e.g. another loop) that didn’t find anything, or because it is iterating over a file that was already read.
UnboundLocalError can also occur when trying to modify a variable that wasn’t already assigned:
def example_increment(): result += 1 example_increment()
This happens because the existing value needs to be looked up before it can be modified, but there is nothing to look up.
Either way, the error will happen even if there is a
var in the global scope, because Python decided ahead of time to treat the variable as local. To solve this, use the
global keyword in addition to giving the initial global value. It must be used in each function that wants to modify the global. (
global in global scope has no effect.)
import random result = 1 def example_increment(): global result result += 1 def example_if(): global result if random.random() < 0.5: result = 1 return result example_increment() # result becomes 2 print(example_if()) # may or may not reset to 1
global is not necessary if the value is read-only. However, a global cannot be used to set an initial value for a local of the same name:
result = 1 def does_not_work(): result = result # trying to set a "default" value for a local if random.random() < 0.5: result = 2 return result
This can’t work either way. As is,
UnboundLocalError will occur. If
global result is added to the function, then
result = result will have no effect, and the function will potentially modify the global (not wanted here). For these cases, the workaround is to simply use a different name for the local.