Don't understand why UnboundLocalError occurs (closure) [duplicate]
Python doesn't have variable declarations, so it has to figure out the scope of variables itself. It does so by a simple rule: If there is an assignment to a variable inside a function, that variable is considered local.[1] Thus, the line
counter += 1
implicitly makes counter
local to increment()
. Trying to execute this line, though, will try to read the value of the local variable counter
before it is assigned, resulting in an UnboundLocalError
.[2]
If counter
is a global variable, the global
keyword will help. If increment()
is a local function and counter
a local variable, you can use nonlocal
in Python 3.x.
You need to use the global statement so that you are modifying the global variable counter, instead of a local variable:
counter = 0def increment(): global counter counter += 1increment()
If the enclosing scope that counter
is defined in is not the global scope, on Python 3.x you could use the nonlocal statement. In the same situation on Python 2.x you would have no way to reassign to the nonlocal name counter
, so you would need to make counter
mutable and modify it:
counter = [0]def increment(): counter[0] += 1increment()print counter[0] # prints '1'
To answer the question in your subject line,* yes, there are closures in Python, except they only apply inside a function, and also (in Python 2.x) they are read-only; you can't re-bind the name to a different object (though if the object is mutable, you can modify its contents). In Python 3.x, you can use the nonlocal
keyword to modify a closure variable.
def incrementer(): counter = 0 def increment(): nonlocal counter counter += 1 return counter return incrementincrement = incrementer()increment() # 1increment() # 2
* The question origially asked about closures in Python.