20

Say I have a function:

x=[]
i=5
while i<=20:
     x.append(i)
     i=i+10
return x

Is there a way to convert it to a list comprehension like this?

newList = [i=05 while i<=20 i=i+10]

I get a syntax error.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
cashmoney11
  • 217
  • 1
  • 2
  • 4
  • 1
    `i` isn't changing in your *while* loop, so it'll simpy *whirl* forever. – Moses Koledoye Mar 09 '17 at 23:25
  • `i` is never modified, so `i <= 5` is always true, and the `while` loop will never exit. – tyteen4a03 Mar 09 '17 at 23:25
  • Possible duplicate of [Using while in list comprehension or generator expressions](http://stackoverflow.com/questions/5505891/using-while-in-list-comprehension-or-generator-expressions) – KoolAid Mar 09 '17 at 23:25
  • 1
    I fixed it, in the real code it's incremented, just forgot to add it here. It still does not work – cashmoney11 Mar 09 '17 at 23:31
  • The fundamental problem here is that initializing an integer and manually incrementing it within a `while` loop is the wrong way to iterate over a sequence of numbers in Python. Your first code block would more appropriately be `x = []; for i in range(5, 21, 10): x.append(i)`, which has a much clearer path for conversion into a comprehension. – TigerhawkT3 Mar 09 '17 at 23:54

3 Answers3

20

You don't need a list comprehension for that. range will just do:

list(range(5, 21, 10)) # [5, 15]

A while loop is not possible inside of a list comprehension. Instead, you could do something like this:

def your_while_generator():
    i = 5
    while i <= 20:
        yield i
        i += 10

[i for i in your_while_generator()]
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Francisco
  • 10,918
  • 6
  • 34
  • 45
16

No, you cannot use while in a list comprehension.

From the grammar specification of Python, only the following atomic expressions are allowed:

atom: ('(' [yield_expr|testlist_comp] ')' |    '[' [testlist_comp] ']' |    '{' [dictorsetmaker] '}' |    NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False')

The expression corresponding to a list comprehension - testlist_comp looks like the following in Python 3:

testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )

Here, the only statements allowed are

test: or_test ['if' or_test 'else' test] | lambdef
star_expr: '*' expr
comp_for: [ASYNC] 'for' exprlist 'in' or_test [comp_iter]

where

comp_if: 'if' test_nocond [comp_iter]
comp_iter: comp_for | comp_if

There is not a single while statement allowed anywhere. The only keywords you are allowed to use is a for, for a for loop.

Solution

Use a for loop, or take advantage of itertools.

Akshat Mahajan
  • 9,543
  • 4
  • 35
  • 44
3

There isn't any syntax for this, but you can use itertools. For example:

In [11]: from itertools import accumulate, repeat, takewhile

In [12]: list(takewhile(lambda x: x <= 20, accumulate(repeat(1), lambda x, _: x + 10)))
Out[12]: [1, 11]

(That's not Pythonic though. The generator solution or explicit solution should be preferred.)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Andy Hayden
  • 359,921
  • 101
  • 625
  • 535