Function definition in a for loop using local variable

Question:

I’m at a loss here.
I’m trying to define a function inside a for loop. The function uses a variable defined inside the loop and could look something similar like that :

myFuns = []
for i in range(10):
    j = i + 4
    def fun(): print(j)
    myFuns += [fun]

At the end of this loop, my functions in myFuns are differents, but they do the same thing, as apparently, this is not a new variable j that is passed to fun(), but the reference of j.

I’d be very glad to know how to pass the value of j and not just the reference.

I didn’t know that a variable created in a loop could outlived the loop, so this is new territory for me here…

Asked By: ogr

||

Answers:

j is a free variable, whose value is looked up when fun is called; fun does not bake the current value of j into its definition. Further, lacking any other containing scope, the call to fun will refer to j in the global scope, where its last set value was its value in the last iteration of the loop.

To actually store a fixed value for j in fun when it is defined, you would need to pass it as a parameter with a default value:

myFuns = []
for i in range(10):
    j = i + 4
    def fun(j=j):
        print(j)
    myFuns.append(fun)  # Don't use += [...] for a single item

However, a closure may be more appropriate:

# Here, j is a free variable in _, but its value comes from the local
# variable j defined by make_fun, not the global scope.
def make_fun(j):
    def _():
        return j
    return _

myFuns = [make_fun(i) for i in range(10)]
Answered By: chepner
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.