On Thu, Jun 4, 2009 at 7:42 PM, Scott David Daniels<scott.dani...@acm.org> wrote: > Brian Quinlan wrote: >> >> This is from Python built from the py3k branch: >> >>> c = (lambda : i for i in range(11, 16)) >> >>> for q in c: >> ... print(q()) >> ... >> 11 >> 12 >> 13 >> 14 >> 15 >> >>> # This is expected >> >>> c = (lambda : i for i in range(11, 16)) >> >>> d = list(c) >> >>> for q in d: >> ... print(q()) >> ... >> 15 >> 15 >> 15 >> 15 >> 15 >> >>> # I was very surprised > > You are entitled to be surprised. Then figure out what is going on. > Hint: it is the moral equivalent of what is happening here: > > >>> c = [] > >>> for i in range(11, 16): > c.append(lambda: i) > > >>> i = 'Surprise!' > >>> print([f() for f in c]) > ['Surprise!', 'Surprise!', 'Surprise!', 'Surprise!', 'Surprise!'] > > >>> i = 0 > >>> print([f() for f in c]) > [0, 0, 0, 0, 0] > > The body of your lambda is an un-evaluated expression with a reference, > not an expression evaluated at the time of loading c. TO get what you > expected, try this: > > >>> c = [] > >>> for i in range(11, 16): > c.append(lambda i=i: i) > > >>> i = 'Surprise!' > >>> print([f() for f in c]) > [11, 12, 13, 14, 15] > > When you evaluate a lambda expression, the default args are evaluated, > but the expression inside the lambda body is not. When you apply that > evaluated lambda expression, the expression inside the lambda body is > is evaluated and returned. >
Getting around this can be pretty easy: c = (lambda i=i: i for i in range(11, 16)) for q in (list(c)): print(q()) -- David blog: http://www.traceback.org twitter: http://twitter.com/dstanek -- http://mail.python.org/mailman/listinfo/python-list