Python closures and stack frames

I use closures quite a lot in python, but the variable lifetime semantics of closures are undocumented as far as I can tell. For example, consider the following code:

    def f():
        a=1
        b=1
        def g():
            return b
        return g

If we call ‘f’ and store the value, ‘b’ will be kept alive. Is ‘a’ kept alive? A naive implementation of closures might store a reference to the entire stack frame of ‘f’ inside the ‘g’ closure, causing ‘a’ to live even though it will never be used. This would be very bad, since generating a closure inside a long function could potentially cause a large memory leak. I wouldn’t expect this since python is implemented by smart people, but it’s worth checking.

Happily, it appears the variable lifetime semantics are as expected. Here’s a test program:

    class A(object):
        def __init__(self,name):
            self.name=name
            print 'creating',name
        def __del__(self):
            print 'destroying',self.name

    def f():
        a=A('a')
        b=A('b')
        c=A('c')
        def g():
            print 'inspecting',b.name
        def h():
            print 'inspecting',c.name
        return g,h

    g,h=f()
    print 'only b and c should be alive'
    del h
    print 'only b should be alive'
    g()
    del g
    print 'done'

The output of this program in CPython is

    creating a
    creating b
    creating c
    destroying a
    only b and c should be alive
    destroying c
    only b should be alive
    inspecting b
    destroying b
    done

All variables die at the correct times, so CPython appears to have correct lifetime semantics in the presence of closures.

Tags: , , ,

Leave a Reply