Igor wrote: > Hi. > > And I thought I understood python pretty well. Until I got hit by this: > >>>> def f(x): > ... print x > >>>> cb = [lambda :f(what) for what in "1234"] >>>> for c in cb:c() > 4 > 4 > 4 > 4
You haven't actually created a closure because you don't have any nested scopes, you have global scope and the scope of the lambda function. A list comprehension doesn't introduce a new scope. Your list comp changes the value of the global what. Here is a simpler version of what you are doing that is not so mysterious: In [8]: what = 3 In [9]: def f(x): ...: print x ...: ...: In [10]: def anon(): ....: f(what) ....: ....: In [11]: anon() 3 In [12]: what = 4 In [13]: anon() 4 Here it is pretty obvious that anon() is referring to the global what, and no surprise that changing what changes the value printed by anon(). There is actually a gotcha here and maybe the code you show is a simplified version of some real code that trips over it. The problem is that the value in a closure is the value that a variable has when the scope creating the closure is exited, not the value when the closure is created. So even if your list comp is in a function (and thus a true closure) you will see the same result: In [14]: def makefuncs(): ....: return [lambda :f(who) for who in "1234"] ....: In [15]: for func in makefuncs(): func() ....: 4 4 4 4 Each function sees the value that who had when makefuncs exited. There are two ways to work around this. One is to use a default argument to the lambda to bind the value, rather than depending on the closure. This would work for your version as well: In [16]: cb = [lambda what=what:f(what) for what in "1234"] In [17]: for c in cb:c() ....: 1 2 3 4 Another way to do it is to make a factory function that creates a single function, and call that in the list comp. Then each value is bound in a separate closure: In [18]: def makefunc(what): ....: return lambda : f(what) ....: In [19]: cb = [makefunc(what) for what in "1234"] In [20]: for c in cb:c() ....: 1 2 3 4 Kent _______________________________________________ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor