'How are python closures implemented?

I am interested in how python implements closures?

For the sake of example, consider this

def closure_test():
    x = 1
    def closure():
        nonlocal x
        x = 2
        print(x)
    return closure

closure_test()()

Here, the function closure_test has a local x which the nested function closure captures.

When I run the program, I get the following output

2

When I see the disassembly of the function closure_test,

  2           0 LOAD_CONST               1 (1)
              2 STORE_DEREF              0 (x)

  3           4 LOAD_CLOSURE             0 (x)
              6 BUILD_TUPLE              1
              8 LOAD_CONST               2 (<code object closure at 0x7f14ac3b9500, file "<string>", line 3>)
             10 LOAD_CONST               3 ('closure_test.<locals>.closure')
             12 MAKE_FUNCTION            8 (closure)
             14 STORE_FAST               0 (closure)

  7          16 LOAD_FAST                0 (closure)
             18 RETURN_VALUE

Disassembly of <code object closure at 0x7f14ac3b9500, file "<string>", line 3>:
  5           0 LOAD_CONST               1 (2)
              2 STORE_DEREF              0 (x)

  6           4 LOAD_GLOBAL              0 (print)
              6 LOAD_DEREF               0 (x)
              8 CALL_FUNCTION            1
             10 POP_TOP
             12 LOAD_CONST               0 (None)
             14 RETURN_VALUE

I see the instructions STORE_DEREF, LOAD_DEREF, MAKE_FUNCTION and LOAD_CLOSURE which I won't get if I write the whole program without functions and closures.

I think those are the instructions which are needed to use closures.

But how does Python manages this? How does it captures the variable off from the local variable table of the enclosing function? And after capturing the variable where does it live? How does the function get the access of the captured variable?

I want a complete low level understanding of how it works.

Thanks in advance.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source