Bug in list comprehensions?

I

Iain King

I was playing with list comprehensions, to try and work out how doubled
up versions work (like this one from another thread: [i for i in
range(9) for j in range(i)]). I think I've figured that out, but I
found something strange along the way:
alpha = ["one", "two", "three"]
beta = ["A", "B", "C"]
[x for x in alpha for y in beta] ['one', 'one', 'one', 'two', 'two', 'two', 'three', 'three', 'three']
[x for x in y for y in beta] ['C', 'C', 'C']
beta = [alpha, alpha, alpha]
beta
[['one', 'two', 'three'], ['one', 'two', 'three'], ['one', 'two',
'three']]
[x for x in y for y in beta] ['C', 'C', 'C']
[y for y in beta]
[['one', 'two', 'three'], ['one', 'two', 'three'], ['one', 'two',
'three']]
['one', 'one', 'one', 'two', 'two', 'two', 'three', 'three', 'three']

Shoudn't both lines '[x for x in y for y in beta]' produce the same
list?
I'm guessing I'm the one confused here... but I'm confused! What's
going on?

Iain
 
F

Fredrik Lundh

Iain said:
I'm guessing I'm the one confused here... but I'm confused! What's
going on?

reading the documentation may help:

/.../ the elements of the new list are those that would be produced
by considering each of the for or if clauses a block, nesting from left
to right, and evaluating the expression to produce a list element each
time the innermost block is reached.

the clauses nest from left to right, not from right to left, so "[x for
x in y for y in beta]" is equivalent to

out = []
for x in y:
for y in beta:
out.append(x)

</F>
 
D

Duncan Booth

Iain said:
[x for x in y for y in beta] ['C', 'C', 'C']
[y for y in beta]
[['one', 'two', 'three'], ['one', 'two', 'three'], ['one', 'two',
'three']]
[x for x in y for y in beta]
['one', 'one', 'one', 'two', 'two', 'two', 'three', 'three', 'three']

Shoudn't both lines '[x for x in y for y in beta]' produce the same
list?

[x for x in y for y in beta] is a shorthand for:

tmp = []
for x in y:
for y in beta:
tmp.append(x)

So x iterates over whatever y is before the loop starts, and y iterates
over beta (but that doesn't affect what x is iterating over).

The important thing is to remember that the order of 'for' and 'if'
statements is the same as though you had written the for loop out in full.
 
S

Sion Arrowsmith

Fredrik Lundh said:
Iain said:
I'm guessing I'm the one confused here... but I'm confused! What's
going on?
the clauses nest from left to right, not from right to left, so "[x for
x in y for y in beta]" is equivalent to

out = []
for x in y:
for y in beta:
out.append(x)

And a list comprehension doesn't get a namespace to itself (cf.
generator comprehensions) so "leaks" its variables. Exactly as
above. So the y being iterated over in "for x in y" is the y
from the previous inner iteration ("for y in beta").
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,961
Messages
2,570,131
Members
46,689
Latest member
liammiller

Latest Threads

Top