From: Neil Cerutti on
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
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