List comp bug?

2006-04-13 Thread tasjaevan
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? I'm using Python 2.4.3

Thanks

James

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: List comp bug?

2006-04-13 Thread Paul Rubin
[EMAIL PROTECTED] writes:
 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))]]

List comprehensions are syntactic sugar for for loops.  The
thing to notice is that in lambda: t, t is unbound.  It's not
the same as the loop index inside the list comp.  Try:

   [f() for f in [lambda t=t: t for t in ((1, 2), (3, 4))]]
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: List comp bug?

2006-04-13 Thread Fredrik Lundh
[EMAIL PROTECTED] 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 



-- 
http://mail.python.org/mailman/listinfo/python-list


Re: List comp bug?

2006-04-13 Thread Terry Reedy

[EMAIL PROTECTED] wrote in message 
news:[EMAIL PROTECTED]
   [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:

List comps were originally designed to be equivalent to for loops with 
nested for loops and if blocks.  Generator expressions are know to be 
slightly different and *not* exactly equivalent due to the new local 
namespace.

[f() for f in (lambda: t for t in ((1, 2), (3, 4)))]
 is giving me
[(1, 2), (3, 4)]

Since, when there is a difference, as above, the genex behavior is more 
often the right or expected behavior (as above), Guido is considering 
making the diference go away in 3.0 by making [stuff] == list((stuff)) (ie, 
listcomp == list(genex)).

Terry Jan Reedy 



-- 
http://mail.python.org/mailman/listinfo/python-list