I have managed to understand what is going on after I rearranged the original code like this:
def foo(val):
return val*val
def make_foo(val):
return lambda : foo(val)
flist = []
for i in range(3):
flist.append(make_foo(i))
def bar1():
for j in range(3,6):
flist.append(lambda : foo(j))
def bar2():
a = lambda n: (lambda:foo(n))
for k in range(6,9):
flist.append(a(k))
bar1()
bar2()
print([f() for f in flist])
Output:
[0, 1, 4, 25, 25, 25, 36, 49, 64]
Notice how the output has only changed slightly: [4,4,4 -> [0,1,4
The reason is that any lambda is also a closure which means that it closes over its surrounding context, which is the local stack frame.
The lambda in make_foo only has the stack frame of the inside of make_foo which only contains val.
In the first loop, make_foo is called three times, so each time a different stack frame is created, with val referring to different values.
In bar1, as before, there is only one lambda and only one stack frame (bar1 is only called once) and the stack frame, containing j ends up with j referring to the value 5.
In bar2, I have explicitly shown that a refers to a single lambda, but that lambda, although it refers to the local stack frame, does not refer to any local variables. During the loop the a lambda is actually called, but that returns another lambda, which, in turn refers to another stack frame. That stack frame is a new one inside a, and each of those stack frames contains and n which, like make_foo, refers to different values.
Another important thing to note is that each lambda is stored in flist. Since flist refers to all the lambdas, all the things that they refer to also still exist. This means that all those stack frames still exist, along with any local variables that the stack frames refer to.
flistcontainslambdas for its first 6 values. These are evaluated when you callf()at which stagei==2andj==5thus the 4s and 25s. Onbar2it seems to me thata(k)returns a lambda where thenis already set... (so you are actually appendinglambda: foo(6), lambda: foo(7), ...). However, not sure how this is explained...