2

I was playing around with closures in Python and I do not understand why the following does not work and how to make it work:

>>> def make_counter():
...     i = 0
...     def inner():
...         i += 1
...         return i
...     return inner
...
>>> c = make_counter()
>>> c()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in inner
UnboundLocalError: local variable 'i' referenced before assignment

Could anybody shed some light on it? Thanks.

jazzblue
  • 2,411
  • 4
  • 38
  • 63
  • In this particular case, you are better off using `c = itertools.count()`. Then use `foo = next(c)` to increment the count – John La Rooy Mar 16 '15 at 03:10

1 Answers1

3

In the inner function, the statement

i += 1

can be understood like this

i = i + 1

since you are assigning a value to i in this function, Python thinks that you are creating a new variable scoped to this current function. And then when it executes the right hand side expression, i + 1, it finds that i has not been assigned any value before using it. That is why it is throwing

UnboundLocalError: local variable 'i' referenced before assignment

To fix this, you need to explicitly tell Python that you are not creating a new variable, instead, you are accessing a variable from the outer scope, with nonlocal (Python 3.x) like this

>>> def make_counter():
...     i = 0
...     def inner():
...         nonlocal i
...         i += 1
...         return i
...     return inner
... 
>>> 
>>> make_counter()()
1

Note: If you are using Python 2.x, follow any of the methods mentioned in this question

Community
  • 1
  • 1
thefourtheye
  • 233,700
  • 52
  • 457
  • 497