
[Giovanni Bajo]
a = [] for i in range(10):
... a.append(lambda: i) ...
print [x() for x in a]
[9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
This subtle semantic of lambda is quite confusing, and still forces people to use the "i=i" trick.
[Greg Ewing]
This has *nothing* to do with the semantics of lambda! It's because Python's for-loop doesn't put its control variable in a new scope, the way Scheme's equivalent construct does.
I don't think I follow that. Scheme has no loops in Python's sense -- things like "do" are shorthand for expressing stylized recursion, where each conceptual iteration gets a fresh set of "loop variables". When people talk about giving a Python for-loop vrbl its own scope, they generally don't mean a new scope on _each iteration_, they just mean that, e.g., i = 5 for i in range(10): # do stuff print i prints 5 intead of 9, about the same as creating a nested block with its own autos in C. The Scheme way is more like: i = 5 def step(i): # do stuff if i < 9: step(i+1) step(0) print i except with tail-recursion elimination. That also prints 5, but does a hell of a lot more than _just_ arrange for that.
*That's* what needs to be addressed to fix this problem. I've made a suggestion about that before, but Guido rejected it, so I won't repeat it here.
Don't recall what that was, but creating a new scope on each iteration sounds hard to explain in Python. If Giovanni wants the Scheme way ;-), it's available: """ a = [] def step(i): a.append(lambda: i) if i < 9: step(i+1) step(0) print [x() for x in a] """ prints [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], although it's more sanely written in Python with a loop: """ def make_lambda(i): return lambda: i a = [] for i in range(10): a.append(make_lambda(i)) print [x() for x in a] """ Abusing the default-argument machinery to capture current bindings is never necessary, and _is_ abuse. Of course I do it too -- but rarely :-)