Prev: Windows - select.select, timeout and KeyboardInterrupt
Next: Picking a license (was Re: new extension generator for C++)
From: Neil Cerutti on 7 May 2010 08:31 On 2010-05-07, Terry Reedy <tjreedy(a)udel.edu> wrote: > On 5/6/2010 3:34 PM, Artur Siekielski wrote: >> Hello. >> I found this strange behaviour of lambdas, closures and list >> comprehensions: >> >>>>> funs = [lambda: x for x in range(5)] >>>>> [f() for f in funs] >> [4, 4, 4, 4, 4] > > You succumbed to lambda hypnosis, a common malady ;-). The > above will not work in 3.x, which does not leak comprehension > iteration variables. It functions the same in 3.1. Python 3.1.1 (r311:74483, Aug 17 2009, 17:02:12) [MSC v.1500 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> funs = [lambda: x for x in range(5)] >>> [f() for f in funs] [4, 4, 4, 4, 4] -- Neil Cerutti *** Your child was bitten by a Bat-Lizard. ***
From: Terry Reedy on 7 May 2010 16:54
On 5/7/2010 8:31 AM, Neil Cerutti wrote: > On 2010-05-07, Terry Reedy<tjreedy(a)udel.edu> wrote: >> On 5/6/2010 3:34 PM, Artur Siekielski wrote: >>> Hello. >>> I found this strange behaviour of lambdas, closures and list >>> comprehensions: >>> >>>>>> funs = [lambda: x for x in range(5)] >>>>>> [f() for f in funs] >>> [4, 4, 4, 4, 4] >> >> You succumbed to lambda hypnosis, a common malady ;-). The >> above will not work in 3.x, which does not leak comprehension >> iteration variables. > > It functions the same in 3.1. > > Python 3.1.1 (r311:74483, Aug 17 2009, 17:02:12) [MSC v.1500 32 bit (Intel)] on > win32 > Type "help", "copyright", "credits" or "license" for more information. >>>> funs = [lambda: x for x in range(5)] >>>> [f() for f in funs] > [4, 4, 4, 4, 4] Ok. >>> x Traceback (most recent call last): File "<pyshell#1>", line 1, in <module> x NameError: name 'x' is not defined #only in 3.x But because the list comp is implemented in 3.x as an anonymous function, which is then called and discarded (an implementation that I believe is not guaranteed by the language ref), the lambda expression defines a nested function which captures the (final) value of x. >>> funs[0].__closure__[0].cell_contents 4 So it works (runs without exception), but somewhat accidentally and for a different reason than in 2.x, where 'x' is 4 at the global level. Terry Jan Reedy |