Rebinding variable outside of the local scope

October 7, 2009

The other day I had to explain why in Python in contrast to Perl/Lisp/Scheme one can’t rebind variable outside of the local scope besides the global scope, i.e. the following function will result in an UnboundLocalError exception in Python 2.x

def outer():
    count = 0
    def inner():
        count += 1 # rebinding
    inner()
    print count
>>> outer()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "scope.py", line 8, in outer
    inner()
  File "scope.py", line 6, in inner
    count += 1 # rebinding
UnboundLocalError: local variable 'count' referenced before assignment

There are several workarounds.

For one thing it is possible to use a variable holding a mutable object:

def outer():
    ns = dict(count=0)
    def inner():
        ns['count'] += 1 # rebinding
    inner()
    print ns['count']
>>> outer()
1

Another approach is to use a function object itself to store the variable:

def outer():
    outer.count = 0
    def inner():
        outer.count += 1 # rebinding
    inner()
    print outer.count
>>> outer()
1

The good news is that there is no need for workarounds anymore in Python 3 which introduced nonlocal keyword:

def outer():
    count = 0
    def inner():
        nonlocal count
        count += 1 # rebinding
    inner()
    print(count)
>>> outer()
1