Reputation: 1304
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