
[Giovanni Bajo]
Yes but:
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.
[Tim Peters]
So stay away from excruciating abuses of lexical scoping you don't understand What do you expect `i` to refer to? "Oh, it should guess that I didn't really mean to defer evaluation of the lambda body at all, but instead evaluate the lambda body at the time I define the lambda and then synthesize some other function that captures the specific outer bindings in effect at lambda-definition time" doesn't really cut it.
I think I understand what happens, I just don't know whether this can be "fixed" or not. Unless you are saying that the above behaviour is not only a complex side-effect the way things are, but the way things should be. Do you agree that it would be ideal if the above code generated range(10) instead of [9]*10, or you believe that the current behaviour is more sound (and if so, why)? As for actual implementing this change of semantic, the fact that `i` is a local variable in the outer scope (assuming it's all within a function), doesn't make it possible for Python to early-bound it, by realizing that, since `i` is not an argument of the lambda, and it's a local of the outer scope? At worse, couldn't Python do the "i=i" trick by itself when it sees that `i` is a local in the outer scope? Right now I can't think off-hand of a case in which this would break things. [Tim Peters]
This isn't typical use for lambda,
Yes, maybe it's not the most used idiom and Andrew wasn't referring to this, but it happens quite often to me (where 'often' means 'many times' among my rare usages of lambda). For instance, in GUI code, it's common to do things like: for b in self.buttons: self.setEventCallback(b, "clicked", lambda: self.label.setText("I pressed button %r" % b)) ... which of course won't work, as written above. Giovanni Bajo