Python is not fixing the value of the loop variable when passing it to a lambda.
xs = ["a", "b", "c"]
print_statements: List[Callable[[], None]] = []
for x in xs:
print_statements.append(lambda: print(f"The value: {x}"))
for print_statement in print_statements:
print_statement()
// Output:
// The value: c
// The value: c
// The value: c
Consider the same example in Java:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args)
{
List<String> xs = List.of("a", "b", "c");
List<Runnable> printStatements = new ArrayList<>();
for (String x : xs)
{
printStatements.add(() -> System.out.println("The value: " + x));
}
for (Runnable printStatement : printStatements)
{
printStatement.run();
}
}
}
// Output:
// The value: a
// The value: b
// The value: c
I have more experience in Java. Thus, the output of the Java program is what I have expected. This is a real gotcha for me in Python and I would like to understand what is happening.
- What is going on in the Python example?
- It seems like the reference to the loop variable is passed
- Is there maybe lazy evaluation going on, which causes this behavior?
- Why has Python been implemented this way? What is the reasoning behind it by the Python devs?
- Could you point me to Python documentation that covers the relevant scoping rules?
- How can I change above Python Code to get the same output as in the Java example