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

  1. 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.
  2. 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()