Reputation: 763
Here is a rather self-explanatory code snippet in python:
globl = 1
def foo():
def bar():
return free+capture
capture = globl #not seen, when bar is defined
return bar
free = 2
a = foo()
globl = 4
b = foo()
print(a()) #3
print(b()) #6
print(a.__closure__[0].cell_contents) # 1
print(b.__closure__[0].cell_contents) # 4
When 'bar' is defined, both 'free' and 'captured' variables are free. they do not exist in parent envirionment, neither in root. When 'bar' returned from 'foo', 'capture' will be captured. From a stack!
So I assume python closes over environment on return of a function. Why is that the case? Why not on definition time of 'bar'?
Same snippet also works if we replace bar with lambda:
bar = lambda : free+capture
Upvotes: 3
Views: 93
Reputation: 49401
at compile-time, when python encounters a function, it makes some determinations. It looks at everything in the function, it does not create a scope or a namespace but it determines which variables are going to be local or nonlocal.
When you run foo(), which means at run-time of foo
, bar
function gets created and python determines "free" and "capture" as non-local, therefore bar
already has a reference to free variables.
"free" and "capture" are in two different scopes but always reference the same "value". When python determines the local variables of "bar", it creates a cell object.
So when outer function "foo" finishes running, this "Cell" object still exists so when inner function "bar" is called, it still gets the same value.
Upvotes: 2