[Tutor] "Strange" behaviour of list comprehension

Oscar Benjamin oscar.j.benjamin at gmail.com
Wed Feb 13 15:13:50 CET 2013


On 13 February 2013 13:45, Mahadevan, Anand <Mahadea at labcorp.com> wrote:
> I'm playing around with list comprehension and in IDLE typed this in.  I actually wanted it to return all tuples satisfying the condition where z is the sum of x and y. I kind of got mixed up with the syntax, hence I put a comma in there instead of an "if".  I'd like some assistance understanding what it's doing...
> Thanks!
>
>>>> somelist = [(x,y,z) for x in range(1,10) for y in range(x,10) for z in range(y,10), x+y==z]

This line doesn't actually work if you paste it into a fresh interpreter:
>>> somelist = [(x,y,z) for x in range(1,10) for y in range(x,10) for z in range(y,10), x+y==z]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'z' is not defined

The clause at the end x+y==z should be preceded by 'if' rather than a
comma. Commas separate function arguments and elements of collections
in displays. Expressions separated by commas without brackets are
interpreted as tuples:

>>> a = 1, 0
>>> a
(1, 0)

So your outermost loop is over a tuple (range(y, 10), x+y==z):
>>> [x for x in 1, 2]
[1, 2]
>>> [x for x in 'a', 'w', 'b']
['a', 'w', 'b']
>>> [x for x in range(3), False]
[[0, 1, 2], False]

Which explains the output you get:

>>>> somelist
> [(1, 1, [1, 2, 3, 4, 5, 6, 7, 8, 9]), (1, 1, False), (1, 2, [2, 3, 4, 5, 6, 7, 8, 9]), (1, 2, False), (1, 3, [3, 4, 5, 6, 7, 8, 9]), (1, 3, False), (1, 4, [4, 5, 6, 7, 8, 9]), (1, 4, False), (1, 5, [5, 6, 7, 8, 9]), (1, 5, False), (1, 6, [6, 7, 8, 9]), (1, 6, False), (1, 7, [7, 8, 9]), (1, 7, False), (1, 8, [8, 9]), (1, 8, False), (1, 9, [9]), (1, 9, False), (2, 2, [2, 3, 4, 5, 6, 7, 8, 9]), (2, 2, False), (2, 3, [3, 4, 5, 6, 7, 8, 9]), (2, 3, False), (2, 4, [4, 5, 6, 7, 8, 9]), (2, 4, False), (2, 5, [5, 6, 7, 8, 9]), (2, 5, False), (2, 6, [6, 7, 8, 9]), (2, 6, False), (2, 7, [7, 8, 9]), (2, 7, False), (2, 8, [8, 9]), (2, 8, False), (2, 9, [9]), (2, 9, False), (3, 3, [3, 4, 5, 6, 7, 8, 9]), (3, 3, False), (3, 4, [4, 5, 6, 7, 8, 9]), (3, 4, False), (3, 5, [5, 6, 7, 8, 9]), (3, 5, False), (3, 6, [6, 7, 8, 9]), (3, 6, False), (3, 7, [7, 8, 9]), (3, 7, False), (3, 8, [8, 9]), (3, 8, False), (3, 9, [9]), (3, 9, False), (4, 4, [4, 5, 6, 7, 8, 9]), (4, 4, False), (4, 5, [5, 6, 7, 8, 9]), (4
>  , 5, False), (4, 6, [6, 7, 8, 9]), (4, 6, False), (4, 7, [7, 8, 9]), (4, 7, False), (4, 8, [8, 9]), (4, 8, False), (4, 9, [9]), (4, 9, False), (5, 5, [5, 6, 7, 8, 9]), (5, 5, False), (5, 6, [6, 7, 8, 9]), (5, 6, False), (5, 7, [7, 8, 9]), (5, 7, False), (5, 8, [8, 9]), (5, 8, False), (5, 9, [9]), (5, 9, False), (6, 6, [6, 7, 8, 9]), (6, 6, False), (6, 7, [7, 8, 9]), (6, 7, False), (6, 8, [8, 9]), (6, 8, False), (6, 9, [9]), (6, 9, False), (7, 7, [7, 8, 9]), (7, 7, False), (7, 8, [8, 9]), (7, 8, False), (7, 9, [9]), (7, 9, False), (8, 8, [8, 9]), (8, 8, False), (8, 9, [9]), (8, 9, False), (9, 9, [9]), (9, 9, False)]

If you put the 'if' keyword in place of the comma it should work:
>>> [x for x in 'a', 'w', 'b' if x != 'b']
['a', 'w']


Oscar


More information about the Tutor mailing list