Skip to the solution
MediumDSA9 min read

What is the late-binding closure pitfall in loops?

352 views

The problem

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 variable i, 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 global i.
  • It affects any function created in a loop (def handlers, callbacks), not only lambdas and comprehensions.
  • Fixes: a default argument lambda i=i: i, a factory function that takes i as a parameter, or functools.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.

  • closures
  • late-binding

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

9 min read Β· 10 sections

Run the code

Edit the code and run it here. Each console line with an expected value becomes a test.

PythonThe bug, and proof that every closure shares one cell
PythonFour fixes and the trade-offs of each

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 98 of 139 in Python

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Python questions
Up nextMedium

How do you use regular expressions in Python?

Continue