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

Discussion in 'Python' started by =?ISO-8859-1?Q?Daniel_Sch=FCle?=, Dec 6, 2005.

  1. 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
     
    =?ISO-8859-1?Q?Daniel_Sch=FCle?=, Dec 6, 2005
    #1
    1. Advertising

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

    D H Guest

    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
     
    D H, Dec 6, 2005
    #2
    1. Advertising

  3. D H wrote:
    > 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
     
    =?ISO-8859-1?Q?Daniel_Sch=FCle?=, Dec 6, 2005
    #3
  4. =?ISO-8859-1?Q?Daniel_Sch=FCle?=

    Guest

    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, 2005
    #4
  5. =?ISO-8859-1?Q?Daniel_Sch=FCle?=

    D H Guest

    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
     
    D H, Dec 6, 2005
    #5
  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
     
    =?ISO-8859-1?Q?Daniel_Sch=FCle?=, Dec 6, 2005
    #6
  7. =?ISO-8859-1?Q?Daniel_Sch=FCle?=

    Duncan Booth Guest

    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?
     
    Duncan Booth, Dec 6, 2005
    #7
  8. =?ISO-8859-1?Q?Daniel_Sch=FCle?=

    Guest

    Daniel Schüle wrote:
    > D H wrote:
    > > 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, 2005
    #8
  9. =?ISO-8859-1?Q?Daniel_Sch=FCle?=

    Duncan Booth Guest

    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.
     
    Duncan Booth, Dec 6, 2005
    #9
  10. 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
     
    Steven Bethard, Dec 6, 2005
    #10
  11. =?ISO-8859-1?Q?Daniel_Sch=FCle?=

    Guest

    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, 2005
    #11
  12. =?ISO-8859-1?Q?Daniel_Sch=FCle?=

    Steve Holden Guest

    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/
     
    Steve Holden, Dec 6, 2005
    #12
  13. 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
     
    Carsten Haese, Dec 6, 2005
    #13
  14. =?ISO-8859-1?Q?Daniel_Sch=FCle?=

    Duncan Booth Guest

    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.
     
    Duncan Booth, Dec 6, 2005
    #14
  15. 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
     
    Chris F.A. Johnson, Dec 6, 2005
    #15
  16. =?ISO-8859-1?Q?Daniel_Sch=FCle?=

    Steve Holden Guest

    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/
     
    Steve Holden, Dec 6, 2005
    #16
  17. On 6 Dec 2005 07:41:45 -0800, 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
     
    Bengt Richter, Dec 6, 2005
    #17
  18. =?ISO-8859-1?Q?Daniel_Sch=FCle?=

    Guest

    Bengt Richter wrote:
    > On 6 Dec 2005 07:41:45 -0800, 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, 2005
    #18
  19. On Tue, 06 Dec 2005 15:44:33 +0000, 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].
    >
    >> 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
     
    Bengt Richter, Dec 6, 2005
    #19
  20. =?ISO-8859-1?Q?Daniel_Sch=FCle?=

    Peter Otten Guest

    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
     
    Peter Otten, Dec 6, 2005
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Kevin Flood
    Replies:
    0
    Views:
    1,023
    Kevin Flood
    Sep 8, 2004
  2. Ben

    Bizzare lst length problem

    Ben, Oct 8, 2006, in forum: Python
    Replies:
    16
    Views:
    431
    Bruno Desthuilliers
    Oct 9, 2006
  3. CarlFK

    parsing grub's menu.lst

    CarlFK, Nov 17, 2008, in forum: Python
    Replies:
    0
    Views:
    282
    CarlFK
    Nov 17, 2008
  4. pozz
    Replies:
    27
    Views:
    747
    Seebs
    Mar 4, 2011
  5. Rob Venable

    Blank space in a drop down lst

    Rob Venable, Jan 16, 2004, in forum: Javascript
    Replies:
    3
    Views:
    126
    Michael Winter
    Jan 16, 2004
Loading...

Share This Page