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, anUnboundLocalErrorexception is raised.UnboundLocalErroris a subclass ofNameError.
...
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
Here 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
Because spam = 'eggs' is never executed, print(spam) raises an UnboundLocalError.
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 with statement.
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
because 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With