nonlocal keyword in Python 2.x nonlocal keyword in Python 2.x python python

nonlocal keyword in Python 2.x


Inner functions can read nonlocal variables in 2.x, just not rebind them. This is annoying, but you can work around it. Just create a dictionary, and store your data as elements therein. Inner functions are not prohibited from mutating the objects that nonlocal variables refer to.

To use the example from Wikipedia:

def outer():    d = {'y' : 0}    def inner():        d['y'] += 1        return d['y']    return innerf = outer()print(f(), f(), f()) #prints 1 2 3


The following solution is inspired by the answer by Elias Zamaria, but contrary to that answer does handle multiple calls of the outer function correctly. The "variable" inner.y is local to the current call of outer. Only it isn't a variable, since that is forbidden, but an object attribute (the object being the function inner itself). This is very ugly (note that the attribute can only be created after the inner function is defined) but seems effective.

def outer():    def inner():        inner.y += 1        return inner.y    inner.y = 0    return innerf = outer()g = outer()print(f(), f(), g(), f(), g()) #prints (1, 2, 1, 3, 2)


Rather than a dictionary, there's less clutter to a nonlocal class. Modifying @ChrisB's example:

def outer():    class context:        y = 0    def inner():        context.y += 1        return context.y    return inner

Then

f = outer()assert f() == 1assert f() == 2assert f() == 3assert f() == 4

Each outer() call creates a new and distinct class called context (not merely a new instance). So it avoids @Nathaniel's beware about shared context.

g = outer()assert g() == 1assert g() == 2assert f() == 5