List comp bug?

Fredrik Lundh fredrik at pythonware.com
Thu Apr 13 07:29:44 EDT 2006


tasjaevan at gmail.com wrote:

>I seem to have stumbled across a problem with list comprehensions (or
> perhaps it's a misunderstanding on my part)
>
>   [f() for f in [lambda: t for t in ((1, 2), (3, 4))]]
>
> is giving me
>
>   [(3, 4), (3, 4)]
>
> The equivalent using a generator expression:
>
>    [f() for f in (lambda: t for t in ((1, 2), (3, 4)))]
>
> is giving me
>
>    [(1, 2), (3, 4)]
>
> as expected.
>
> Is this a known bug?

no, it's not a bug, it's a consequence of the order in which things are done,
and different visibility rules for the loop variables used in list comprehensions
and generator expressions.

both the inner loops generates lambda expressions that return the value of
the "t" variable.

for the list comprehension, "t" is an ordinary variable (part of the surrounding
scope), and since the comprehension is completed before the resulting list is
returned, all lambdas end up referring to the same "t", which is set to the last
value:

>>> x = [lambda: t for t in ((1, 2), (3, 4))]
>>> x
[<function <lambda> at 0x00A87AB0>, <function <lambda> at 0x00A876F0>]
>>> x[0]()
(3, 4)
>>> t = "hello"
>>> x[0]()
'hello'

in contrast, the generator expression uses a local loop variable "t", and only fetches
one value from the target sequence for each iteration, so all lambdas will be bound
to different objects.

any special reason you need to write this kind of convoluted code, btw?

</F> 






More information about the Python-list mailing list