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

  • Thread starter =?ISO-8859-1?Q?Daniel_Sch=FCle?=
  • Start date
?

=?ISO-8859-1?Q?Daniel_Sch=FCle?=

Hello NG,

I am wondering if there were proposals or previous disscussions in this
NG considering using 'while' in comprehension lists

# 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)



usually I would prefer one liners like
lines=[line.strip() for line in file("foo").readlines() if line]
they make the purpose clear
so if 'while' were allowed in comprehension list this would allow
to write concise code

to the example above, I tried a workaround
i=2
lst=[i**=2 for _ in iter(lambda:_<1000, False)]

but this failes with SyntaxError because of i**=2
and must be also rewritten into
.... global i
.... i**=2
.... return i
....
>>> lst=[f() for _ in iter(lambda:i<1000, False)]
>>> lst
[4, 16, 256, 65536]

I think this loses compared with
i=2
lst=[i**=2 while i<1000]

Regards, Daniel
 
D

D H

Daniel said:
Hello NG,

I am wondering if there were proposals or previous disscussions in this
NG considering using 'while' in comprehension lists

# 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)

That would loop endlessly since you don't increment i.
You can use i**=2 for i in range(1000) instead
 
?

=?ISO-8859-1?Q?Daniel_Sch=FCle?=

D said:

lst=[i**2 for i in range(1000)]

you will get a list with 1000 items
[0,1,4,9 ... ]

is not the same as

i,lst=2,[]
while i<1000:
i**=2
lst.append(i)

here you get [4,16,256,65536]
only 4 items

Regards, Daniel
 
B

bonono

D said:
Daniel said:
Hello NG,

I am wondering if there were proposals or previous disscussions in this
NG considering using 'while' in comprehension lists

# 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)

That would loop endlessly since you don't increment i.
You can use i**=2 for i in range(1000) instead

I don't think one can use assignment in list comprehension or generator
expression. The limitation is very much like lambda.
 
?

=?ISO-8859-1?Q?Daniel_Sch=FCle?=

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]


Regards, Daniel
 
D

Duncan Booth

Daniel said:
I am wondering if there were proposals or previous disscussions in this
NG considering using 'while' in comprehension lists

# 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?
 
B

bonono

Daniel said:
D said:

lst=[i**2 for i in range(1000)]

you will get a list with 1000 items
[0,1,4,9 ... ]

is not the same as

i,lst=2,[]
while i<1000:
i**=2
lst.append(i)

here you get [4,16,256,65536]
only 4 items
You want a combination of takewhile and scanl and filter. For this
particular snippet, I think a simple loop is cleaner. I am bias towards
one-liner but for this case, explicit loop beats it. Just define a
short function.
 
D

Duncan Booth

Daniel said:
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.
 
S

Steven Bethard

Daniel said:
I am wondering if there were proposals or previous disscussions in this
NG considering using 'while' in comprehension lists

# pseudo code
i=2
lst=[i**=2 while i<1000]

I haven't had much need for anything like this. Can't you rewrite with
a list comprehension something like::
>>> [4**(2**i) for i in xrange(math.log(1000, 4))]
[4, 16, 256, 65536]

?

STeVe
 
B

bonono

Duncan said:
Daniel said:
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()))
 
S

Steve Holden

Daniel said:
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

In that case, kindly explain how the condition i<1000 can become false
when it starts at 2 and never changes! [In other words: you *are*
missing something obvious].
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]
Indeed. But the test condition is initially true, and can never become
false, so the loop is endless. It will probably eventually terminate by
throwing a MemoryError exception when lst and its element values use up
all available space.

Don't you have an interpreter you could run the code in to verify that
it does indeed loop interminably? You seem to be assuming that the
expression i**2 changes the value of i. It doesn't.

regards
Steve
 
C

Carsten Haese

Daniel said:
i=2
lst=[]
while i<1000:
i**=2
lst.append(i)

unless I am missing something obvious, I can not see why the loop should
not terminate

In that case, kindly explain how the condition i<1000 can become false
when it starts at 2 and never changes! [In other words: you *are*
missing something obvious].

Don't you have an interpreter you could run the code in to verify that
it does indeed loop interminably? You seem to be assuming that the
expression i**2 changes the value of i. It doesn't.

Note that the OP wrote i**=2, not i**2.

-Carsten
 
D

Duncan Booth

Steve said:
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)
....
Don't you have an interpreter you could run the code in to verify that
it does indeed loop interminably? You seem to be assuming that the
expression i**2 changes the value of i. It doesn't.

I think that like me you read 'i**2' when the OP actually wrote 'i**=2'.
i**=2 will change the value of i in the conventional while loop. In the
list comprehension it is of course a syntax error even if you assume list
comprehensions are expanded to allow the while.
 
C

Chris F.A. Johnson

Daniel said:
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

In that case, kindly explain how the condition i<1000 can become false
when it starts at 2 and never changes! [In other words: you *are*
missing something obvious].

What does i**=2 do if not change i?
.... i**=2
.... lst.append(i)
.... [4, 16, 256, 65536]
 
S

Steve Holden

Carsten said:
Daniel said:
i=2
lst=[]
while i<1000:
i**=2
lst.append(i)


unless I am missing something obvious, I can not see why the loop should
not terminate

In that case, kindly explain how the condition i<1000 can become false
when it starts at 2 and never changes! [In other words: you *are*
missing something obvious].

Don't you have an interpreter you could run the code in to verify that
it does indeed loop interminably? You seem to be assuming that the
expression i**2 changes the value of i. It doesn't.


Note that the OP wrote i**=2, not i**2.
Oops. Thanks :)

regards
Steve
 
B

Bengt Richter

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

import operator
x=3D[2]
lst=3Dlist(((operator.setitem(x,0,x[0]**2),x[0])[1] for _ in
xrange(10000000) if x[0] < 1000 or iter([]).next()))
Or
>>> list(iter(lambda b=[2]:b.append(b[0]**2) or b[0]<1000 and b.pop(0) or None, None))
[2, 4, 16, 256]

Regards,
Bengt Richter
 
B

bonono

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

import operator
x=3D[2]
lst=3Dlist(((operator.setitem(x,0,x[0]**2),x[0])[1] for _ in
xrange(10000000) if x[0] < 1000 or iter([]).next()))
Or
list(iter(lambda b=[2]:b.append(b[0]**2) or b[0]<1000 and b.pop(0) or None, None))
[2, 4, 16, 256]
out of curiosity, what stops the iterator ?
 
B

Bengt Richter

Daniel said:
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

In that case, kindly explain how the condition i<1000 can become false
when it starts at 2 and never changes! [In other words: you *are*
missing something obvious].
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]
Indeed. But the test condition is initially true, and can never become
false, so the loop is endless. It will probably eventually terminate by
throwing a MemoryError exception when lst and its element values use up
all available space.

Don't you have an interpreter you could run the code in to verify that
it does indeed loop interminably? You seem to be assuming that the
expression i**2 changes the value of i. It doesn't.
No, but i**=2 does. Are you two talking about the same code?
>>> i=2
>>> lst=[]
>>> while i<1000:
... i**=2
... lst.append(i)
... [4, 16, 256, 65536]

Regards,
Bengt Richter
 
P

Peter Otten

 list(iter(lambda b=[2]:b.append(b[0]**2) or b[0]<1000 and b.pop(0) or
None, None)) [2, 4, 16, 256]
out of curiosity, what stops the iterator ?

"""
Help on built-in function iter in module __builtin__:

iter(...)
iter(collection) -> iterator
iter(callable, sentinel) -> iterator

Get an iterator from an object. In the first form, the argument must
supply its own iterator, or be a sequence.
In the second form, the callable is called until it returns the
sentinel.
"""

The lambda is used as the callable, None as the sentinel.

Peter
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top