Problem
What will this code print out?
def make_functions():
flist = []
for i in [1, 2, 3]:
def print_i():
print(i)
flist.append(print_i)
return flist
functions = make_functions()
for f in functions:
f()
How can we make it print out what we apparently want?
Solution
Method 1 - Fix the closures
The answer of the above function will be:
Output:
3
3
3
Explanation: All functions print the last value of `i`, which is 3, due to closure capturing the variable reference, not the value.
The original code captures the variable i
in the closure, meaning all functions reference the same memory location for i
. When the loop ends, the value of i
is 3, which is why all functions print 3. To fix this, we need to capture the value of i
at each iteration, not the variable reference.
Approach
- Python Solution Fix using Default Arguments:
One way to fix the issue is to use default arguments in the inner function to capture the current value of
i
. - Java Solution Using Functional Interface: Since Java doesn’t have closures in the same way, we will create a functional interface and use lambdas.
Fixed Code
class Solution:
def make_functions(self):
flist = []
for i in [1, 2, 3]:
def print_i(i=i): # Use default argument to capture value of i
print(i)
flist.append(print_i)
return flist
# Testing the fix
solution = Solution()
functions = solution.make_functions()
for f in functions:
f()