AlQuemist
AlQuemist

Reputation: 1304

Shared and localized variables in Python closures

Closures in Python behave in an “odd” way, so to say. Consider the following code snippet where I have tried to build a list of closures based on foo in two ways: In bad_closure, closures are built ‘on the fly’, while in good_closure the closures are built by a helper function:

def foo(d):
    return d + 1

def bad_closure():
    ''' shares resources implicitly '''

    # list of 5 closures
    # `i` is shared between all closures
    cls = [lambda : foo(i) for i in range(5)]
    return cls

def good_closure():
    ''' no resource sharing '''

    def mk_cl(i):
        ''' helper to make a closure'''
        c_ = lambda : foo(i)
        return c_

    # list of 5 closures
    # each closure has its own `i`
    cls = [mk_cl(i) for i in range(5)]
    return cls

#--- TEST ---
bs = bad_closure()
print([f() for f in bs]) # output: [5, 5, 5, 5, 5]

gs = good_closure()
print([f() for f in gs]) # output: [1, 2, 3, 4, 5]

The results are astoundingly different. It seems that in bad_closure, the closures take a fixed i each, but they all share the same i which updated by each iteration (and finally takes the value 5)! In contrast, in good_closure, i's are separate — as I expect.

I'd like to see what is happening behind the scenes and why.

Upvotes: 0

Views: 26

Answers (0)

Related Questions