How can I return a function that uses the value of a variable?

Question:

I want to write a function which returns a list of functions. As a MWE, here’s my attempt at function that gives three functions that add 0, 1, and 2 to an input number:

def foo():
    result = []
    for i in range(3):
        temp = lambda x: x + i
        print(temp(42))  # prints 42, 43, 44
        result.append(temp)
    return result

for f in foo():
    print(f(42))  #prints 44, 44, 44

Contrary to my expectation, each function ends up using the last value taken by i. I’ve experienced similar behavior when e.g. a list is used as argument to a function but Python actually uses a pointer to the list, but here i is an integer, so I don’t understand what’s going on here. I’m running Python 3.5.

Asked By: bjarkemoensted

||

Answers:

Closures bind late, meaning they will use the last value of i in the scope they have been defined when called (in this case the last value of i will be 2).

The common solution to this is providing the value of i as a default argument:

temp = lambda x, i=i: x + i

Since Python evaluates default arguments during the construction of a function, this is a trick that helps Python use the correct value of i when the callable is invoked, it doesn’t create a closure and, instead, can look i up in it’s locals.

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.