Question presented to candidate:
"What does [f() for f in [lambda: i for i in range(3)]] return, and why? How would you fix it?"
What a strong answer should cover:
- The output is
[2, 2, 2]: each lambda captures the variablei, not its value, and reads it when called, after the loop has finished. - The mechanism: all the functions share one cell for
i(provable with__closure__); at module level there is no cell at all, they read the globali. - It affects any function created in a loop (
defhandlers, callbacks), not only lambdas and comprehensions. - Fixes: a default argument
lambda i=i: i, a factory function that takesias a parameter, orfunctools.partial; trade-offs of each (a default can be overridden by callers). - A default argument snapshots the object, not its contents: capturing a mutable list still shares it.
Code / implementation expected: Yes β predict the output, then show at least one fix and explain why it works.