Daily Coding Day Ninety One

Another few days another programming problem! This one is python specific, or perhaps other anonymoys capabale languages, related to the handling of iteration with said functions.

The Problem:

Consider the following code snippet:

1
2
3
4
5
6
functions = []
for i in range(10):
functions.append(lambda : i)

for f in functions:
print(f())

At first glance, you might expect this code to print the numbers 0 through 9. However, when you run it, you’ll see that it prints:

1
2
3
4
5
6
7
8
9
10
9
9
9
9
9
9
9
9
9
9

Why does this happen?

The issue arises from how Python handles closures and the lambda function. In this loop each lambda function you append to the list functions captures the variable i. However, it doesn’t capture the value of i at the time the lambda is created but instead it captures a reference to the variable itself. By the time the lambda is executed, the loop has completed, and i has the value 9. As a result, each lambda function prints the current value of i, which is 9.

How can we fix it?

To ensure each lambda function captures the correct value of i at the time it is created, I use a binding for the variable i. By using lambda i=i: i a default argument for the lambda functionis evaluated at the time the lambda is created, thus capturing the current value of i. Each lambda function now has its own separate binding to the value of i, which solves the problem. Here’s how you can modify the code to behave as expected:

1
2
3
4
5
6
functions = []
for i in range(10):
functions.append(lambda i=i: i) # Capture the current value of i

for f in functions:
print(f())

With this change, the code will now print:

1
2
3
4
5
6
7
8
9
10
0
1
2
3
4
5
6
7
8
9