On 5/7/2010 8:31 AM, Neil Cerutti wrote:

> On 2010-05-07, Terry Reedy<(E-Mail Removed)> 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