i=2; lst=[i**=2 while i<1000]

bonono at gmail.com bonono at gmail.com
Tue Dec 6 10:41:45 EST 2005


Duncan Booth wrote:
> Daniel Schüle wrote:
>
> > hi,
> >
> > [...]
> >
> >>># pseudo code
> >>>i=2
> >>>lst=[i**=2 while i<1000]
> >>>
> >>>of course this could be easily rewritten into
> >>>i=2
> >>>lst=[]
> >>>while i<1000:
> >>>     i**=2
> >>>     lst.append(i)
> >>>
> >>
> >>
> >> Neither of these loops would terminate until memory is exhausted. Do
> >> you have a use case for a 'while' in a list comprehension which would
> >> terminate?
> >
> > unless I am missing something obvious, I can not see why the loop
> > should not terminate
> > sure pseudo code is not executable but the other one works
> > while tests the boolean expression first then decides whether to
> > execute the body or not, in particular no next-iterator is
> > involved(??) as it would be in
> > lst=range(5)
> > for i in lst:
> >      del lst[0]
> >
> Yes, I wasn't paying attention. The pseudo-code fails because you would
> need to support assignment and generating a value inside the loop, but the
> simple loop does work.
>
> The simple case in the pseudo-coded loop isn't nearly general enough, what
> if you wanted a tuple, or i**2+1 as each loop value. You would need syntax
> which generate more complex list values e.g:
>
> lst = [ (i, i**2) while i < 1000; i**=2 ]
>
> One current way to write this would be:
>
> def squaring(start, end):
>   i = start
>   while i < end:
>       yield i
>       i = i**2
>
> Then you can do:
>
>    lst = [(i, i**2) for i in squaring(1, 1000) ]
>
> which has the advantage of pulling all the complex logic out of the list
> comprehension.

If one really wants a very messy one-liner, it is possible

import operator
x=[2]
lst=list(((operator.setitem(x,0,x[0]**2),x[0])[1] for _ in
xrange(10000000) if x[0] < 1000 or iter([]).next()))




More information about the Python-list mailing list