Closure Late Binding in a Loop
Problem
An HTTP framework registers one handler per route. To avoid repeating the dispatch boilerplate, the handlers are created in a loop:
def dispatch(route: str, request: str) -> str:
return f"{route} handled {request}"
def build_handlers(routes: list[str]) -> dict[str, "Callable[[str], str]"]:
handlers = {}
for route in routes:
handlers[route] = lambda request: dispatch(route, request)
return handlers
handlers = build_handlers(["/users", "/orders", "/health"])
print(handlers["/users"]("GET"))Symptom: every route is handled as if it were /health. The line above prints /health handled GET. The dictionary keys are correct (/users, /orders, /health), only the behaviour is wrong. Explain what is printed and why, and fix build_handlers.
Examples
handlers["/users"]("GET")→ expected/users handled GET. Actual/health handled GET.handlers["/orders"]("POST")→ expected/orders handled POST. Actual/health handled POST.handlers["/health"]("GET")→/health handled GET. Correct only because it happens to be the last route.
Hints
- When is the name
routeinside the lambda looked up: when the lambda is created, or when it is called? - How many distinct variables named
routeexist inbuild_handlers? One per iteration, or one for the whole loop? - Give each lambda its own copy of the value at creation time. Default arguments are evaluated at definition time.
Last reviewed 8 September 2026
Approach · Solution (Python) · Complexity · Follow-ups · Company variations · Tests
The rest of this question — the worked approach, the Python solution with passing tests, complexity, follow-ups and how each company frames it — is part of the guides.
Get the full guide
Pick the company you're interviewing with. Each guide has every question tiered for that loop — one-time purchase, lifetime access.
Also in: Apple, Google, Meta, Microsoft, Netflix
Interviewing at more than one? All 6 guides for $499 · save $395
Not ready to buy? Get the free starter pack — 13 questions with full solutions.