A Fresh Cell Per Call Is Not the Loop Bug

def setup():
    def make_func(i):
        return lambda: i * 10
    return [make_func(i) for i in range(3)]

funcs = setup()
print([f() for f in funcs])

What does this print, and why?

A

[0, 0, 0], because make_func returns before its i is ever used, so the closure loses track of which value it had

B

[0, 10, 20], because each call to make_func binds i to a new parameter that's independent of any other call's i

C

[20, 20, 20], because all the lambdas still close over one shared loop variable i

D

[0, 10, 20], because a lambda always captures the value of any variable it uses at the moment the lambda is created