Closure in python?

closures, python, python-2.x

Solution

Python 2.x has a syntax limitation that doesn't allow to capture a variable in read/write.

The reason is that if a variable is assigned in a function there are only two possibilities:

- the variable is a global and has been declared so with `global x`

- the variable is a local of the function

more specifically it's ruled out that the variable is a local of an enclosing function scope

This has been superseded in Python 3.x with the addition of `nonlocal` declaration. Your code would work as expected in Python 3 by changing it to

def make_adder_and_setter(x):
    def setter(n):
        nonlocal x
        x = n

    return (lambda y: x + y, setter)

The python 2.x runtime is able to handle read-write closed over variable at a bytecode level, however the limitation is in the syntax that the compiler accepts.

You can see a lisp compiler that generates python bytecode directly that creates an adder closure with read-write captured state at the end of this video. The compiler can generate bytecode for Python 2.x, Python 3.x or PyPy.

If you need closed-over mutable state in Python 2.x a trick is to use a list:

def make_adder_and_setter(x):
    x = [x]
    def setter(n):
        x[0] = n

    return (lambda y: x[0] + y, setter)

Problem

When I run this code, I get this result: ``` 15 15 ``` I expect the output should be ``` 15 17 ``` but it is not. The question is: why? ``` def make_adder_and_setter(x): def setter(n): x = n return (lambda y: x + y, setter) myadder, mysetter = make_adder_and_setter(5) print myadder(10) mysetter(7) print myadder(10) ```

Original source