Robert Kern <[EMAIL PROTECTED]> writes: > Juan Pablo Romero wrote: >> Hello! >> >> given the definition >> >> def f(a,b): return a+b >> >> With this code: >> >> fs = [ lambda x: f(x,o) for o in [0,1,2]] >> >> or this >> >> fs = [] >> for o in [0,1,2]: >> fs.append( lambda x: f(x,o) ) >> >> I'd expect that fs contains partial evaluated functions, i.e. >> >> fs[0](0) == 0 >> fs[1](0) == 1 >> fs[2](0) == 2 >> >> But this is not the case :( >> >> What is happening here? > > Namespaces. The functions are looking up o at runtime. In both cases, o > is bound to the last object in [0,1,2] once the iteration is finished. > > Try this (although I'm sure there are better ways): > > In [4]: fs = [lambda x, o=o: f(x, o) for o in [0,1,2]] > > In [5]: fs[0](0) > Out[5]: 0 > > In [6]: fs[0](1) > Out[6]: 1 > > In [7]: fs[0](2) > Out[7]: 2
Right explanation. Right solution. Wrong examples. He wanted to see: >>> fs[0](0) 0 >>> fs[1](0) 1 >>> fs[2](0) 2 >>> List comprehensions were purposely designed to mimic for loops, which (unlike other languages) don't create a new variable for each pass through the loop. ((They also "leak" the variable to the surrounding namespace.) So you need to capture the current value of the loop index somewhere. An alternative (and maybe slightly cleaner) method is: >>> def makef(a): ... return lambda b: a + b ... >>> fs = [makef(o) for o in [0, 1, 2]] >>> fs[0](0) 0 >>> fs[1](0) 1 >>> fs[2](0) 2 >>> Generator comprehensions have the same issue: >>> fs = list(lambda x: f(o, x) for o in [0, 1, 2]) >>> fs[0](0) 2 >>> fs[1](0) 2 >>> fs[2](0) 2 >>> <mike -- Mike Meyer <[EMAIL PROTECTED]> http://www.mired.org/home/mwm/ Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information. -- http://mail.python.org/mailman/listinfo/python-list