473,320 Members | 2,097 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

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

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
i=2
def f(): .... 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

Dec 6 '05 #1
21 1800
D H
Daniel Schüle wrote:
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
Dec 6 '05 #2

D H wrote:
Daniel Schüle wrote:
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.

Dec 6 '05 #3
D H
bo****@gmail.com wrote:
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.


i**2
Dec 6 '05 #4
Daniel Schüle wrote:
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?
Dec 6 '05 #5
D H wrote:
bo****@gmail.com wrote:
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.


i**2


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

Dec 6 '05 #6
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

Dec 6 '05 #7

Daniel Schüle wrote:
D H wrote:
bo****@gmail.com wrote:
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.


i**2


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.

Dec 6 '05 #8
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.
Dec 6 '05 #9
Daniel Schüle wrote:
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
Dec 6 '05 #10

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

Dec 6 '05 #11
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


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
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC www.holdenweb.com
PyCon TX 2006 www.python.org/pycon/

Dec 6 '05 #12
On Tue, 2005-12-06 at 10:44, Steve Holden wrote:
Daniel Schüle wrote:
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
Dec 6 '05 #13
Steve Holden wrote:
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.
Dec 6 '05 #14
On 2005-12-06, Steve Holden 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


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=[]
while i<1000: .... i**=2
.... lst.append(i)
.... lst

[4, 16, 256, 65536]
--
Chris F.A. Johnson, author | <http://cfaj.freeshell.org>
Shell Scripting Recipes: | My code in this post, if any,
A Problem-Solution Approach | is released under the
2005, Apress | GNU General Public Licence
Dec 6 '05 #15
On 6 Dec 2005 07:41:45 -0800, bo****@gmail.com wrote:

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
Dec 6 '05 #16

Bengt Richter wrote:
On 6 Dec 2005 07:41:45 -0800, bo****@gmail.com wrote:

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 ?

Dec 6 '05 #17
Carsten Haese wrote:
On Tue, 2005-12-06 at 10:44, Steve Holden wrote:
Daniel Schüle wrote:
>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
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC www.holdenweb.com
PyCon TX 2006 www.python.org/pycon/

Dec 6 '05 #18
On Tue, 06 Dec 2005 15:44:33 +0000, Steve Holden <st***@holdenweb.com> 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


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)
... lst

[4, 16, 256, 65536]

Regards,
Bengt Richter
Dec 6 '05 #19
bo****@gmail.com wrote:
>*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
Dec 6 '05 #20
<bo****@gmail.com> wrote:
Bengt Richter wrote:
>>> 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 ?


<http://docs.python.org/lib/built-in-funcs.html>:

iter(o, sentinel) [ ... ]
The iterator created in this case will call o with no arguments for
each call to its next() method; if the value returned is equal to
sentinel, StopIteration will be raised, otherwise the value will be
returned.

In this case, o is:

lambda b=[2]:b.append(b[0]**2) or b[0]<1000 and b.pop(0) or None

which returns None when b[0]>=1000 (None or (False and _) or None
evaluates to the last None).

--
\S -- si***@chiark.greenend.org.uk -- http://www.chaos.org.uk/~sion/
___ | "Frankly I have no feelings towards penguins one way or the other"
\X/ | -- Arthur C. Clarke
her nu becomeþ se bera eadward ofdun hlæddre heafdes bæce bump bump bump
Dec 6 '05 #21
Daniel Schüle wrote:
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]


You are actually describing two features that list comps don't natively support
- while-based termination, and calculating based on prior values of output. Of
course there are work-arounds for both, which others have shown. Here's another
approach:

The while-based termination can be easily achieved using itertools.takewhile, e.g.,:
list(itertools.takewhile(lambda x: x < 10, range(100))) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
the harder piece is to access the prior value. One way is like this:

def chasetail(start, func):
from itertools import tee
def mygen():
yield start
for i in (func(i) for i in iterators[0]):
yield i
iterators = tee(mygen())
return iterators[1]

the trick is to create two independent iterators, using itertools.tee, one of
which is consumed internally in the func(i) for i in iterators[0] generator
expression, the other is returned to use code.
it = chasetail(2, lambda x: x*x) #careful - this won't terminate
it.next() 2 it.next() 4 it.next() 16 it.next() 256 it.next() 65536
Then you can combine these two approaches to get something semantically like
what you wanted in the first place (although not as pretty ;-)
list(itertools.takewhile(lambda x: x < 1000, chasetail(2, lambda x: x*x))) [2, 4, 16, 256]
If you like this sort of thing, you might want to generalize the concept with a
Stream class. Here's minimal implementation:

import itertools as it

class Stream(object):
"""An extendable stream, that provides a separate iterator
(using itertools.tee) on every iteration request"""

def __init__(self, *iterables):
self.queue = list(iterables)
self.itertee = it.tee(self._chain(self.queue))[0]

def _chain(self, queue):
while queue:
for i in self.queue.pop(0):
self.head = i
yield i

def extend(self,other):
self.queue.append(other)

def __iter__(self):
"""Normal iteration over the iterables in self.queue in turn"""
return self.itertee.__copy__()
then, you can write your squaring algorithm as:
s= Stream([2])
s.extend(it.takewhile(lambda x: x < 1000, (i**2 for i in s)))
list(s)

[2, 4, 16, 256]
Michael


Dec 6 '05 #22

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Lilou | last post by:
Hello this page works : http://lilou.leuwen.chez.tiscali.fr/testlilou.htm the source : .... a.link:hover div.test2 {display : block; position: absolute; z-index: 1000;
7
by: JustSomeGuy | last post by:
I have a double that I want to output as: (depending on its value) 1000 Bytes 1.6 Kilobyte 2.5 Megabytes ..5 Terabytes can I do this with... ostream & operator<<(ostream & o, double n)
47
by: VK | last post by:
Or why I just did myArray = "Computers" but myArray.length is showing 0. What a hey? There is a new trend to treat arrays and hashes as they were some variations of the same thing. But they...
14
by: LumisROB | last post by:
Is it possible to create matrixes with vector <vector <double >> ? If it is possible which is the element m23 ? You excuse but I am not an expert Thanks ROB
1
by: RJN | last post by:
Hi I'm using XMLTextReader to parse the contents of XML. I have issues when the xml content itself has some special characters like & ,> etc. <CompanyName>Johnson & Jhonson</CompanyName>...
9
by: Simple Simon | last post by:
Java longs are 8 bytes. I have a Java long that is coming in from the network, and that represents milliseconds since Epoch (Jan 1 1970 00:00:00). I'm having trouble understanding how to get it...
6
by: =?iso-8859-2?Q?K=F8i=B9tof_=AEelechovski?= | last post by:
At <http://jibbering.com/faq/index.html#FAQ4_41> IS Microsoft introduced a shortcut that can be used to reference elements which include an ID attribute where the ID becomes a global variable....
16
by: njsimha | last post by:
Hi, I have the following XML snippet: <root> <template1> <elem1>1000</elem1> <elem2> <subelem1>65</subelem1>
2
by: njsimha | last post by:
Hi, I have a query regarding the selection of a particular tag based on a condition. In the following XML code: <root> <template1> <elem1>1000</elem1> <elem2>
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.