• iterations destroy reversed() results

    From Pierre Fortin@21:1/5 to All on Fri Sep 1 12:15:45 2023
    Hi,

    reversed() results are fine until iterated over, after which the
    results are no longer available. This was discovered after using
    something like this:

    rev = reversed( sorted( list ) )
    sr = sum( 1 for _ in rev )
    # rev is now destroyed

    So reversed() results can only be iterated once unlike sorted(), etc...

    Script to illustrate the issue:
    /tmp/rev:
    orig = [ 'x', 'a', 'y', 'b', 'z', 'c' ]
    co = sum( 1 for _ in orig )
    print( 'orig', orig, co )
    # reversing
    rev = reversed(orig)
    print( 'before iteration:', [ x for x in rev ] )
    # list comprehension was an iteration over 'rev'
    print( 'after iteration:', [ x for x in rev ] )
    # how this was discovered...
    orig = [ 'x', 'a', 'y', 'b', 'z', 'c' ]
    rev = reversed(orig)
    cr = sum( 1 for _ in rev )
    print( 'after sum():', [ x for x in rev ] )

    which produces:

    $ python /tmp/rev
    orig ['x', 'a', 'y', 'b', 'z', 'c'] 6
    before iteration: ['c', 'z', 'b', 'y', 'a', 'x']
    after iteration: []
    after sum(): []

    Regards,
    Pierre

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dom Grigonis@21:1/5 to All on Mon Sep 4 00:52:58 2023
    It is by design. `sorted` returns a list, while `reversed` returns an iterator. Iterators are exhaust-able, and not reusable. So be mindful of this and if you are going to "re-use” the sequence returned by iterator, convert it to list first.

    Have a look at `itertools` library, which contains a lot of such functions and many good recipes on achieving various things elegantly using iterators.

    On 1 Sep 2023, at 19:15, Pierre Fortin via Python-list <python-list@python.org> wrote:

    Hi,

    reversed() results are fine until iterated over, after which the
    results are no longer available. This was discovered after using
    something like this:

    rev = reversed( sorted( list ) )
    sr = sum( 1 for _ in rev )
    # rev is now destroyed

    So reversed() results can only be iterated once unlike sorted(), etc...

    Script to illustrate the issue:
    /tmp/rev:
    orig = [ 'x', 'a', 'y', 'b', 'z', 'c' ]
    co = sum( 1 for _ in orig )
    print( 'orig', orig, co )
    # reversing
    rev = reversed(orig)
    print( 'before iteration:', [ x for x in rev ] )
    # list comprehension was an iteration over 'rev'
    print( 'after iteration:', [ x for x in rev ] )
    # how this was discovered...
    orig = [ 'x', 'a', 'y', 'b', 'z', 'c' ]
    rev = reversed(orig)
    cr = sum( 1 for _ in rev )
    print( 'after sum():', [ x for x in rev ] )

    which produces:

    $ python /tmp/rev
    orig ['x', 'a', 'y', 'b', 'z', 'c'] 6
    before iteration: ['c', 'z', 'b', 'y', 'a', 'x']
    after iteration: []
    after sum(): []

    Regards,
    Pierre
    --
    https://mail.python.org/mailman/listinfo/python-list

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Passin@21:1/5 to Pierre Fortin via Python-list on Sun Sep 3 18:19:11 2023
    On 9/1/2023 12:15 PM, Pierre Fortin via Python-list wrote:
    Hi,

    reversed() results are fine until iterated over, after which the
    results are no longer available. This was discovered after using
    something like this:

    rev = reversed( sorted( list ) )
    sr = sum( 1 for _ in rev )
    # rev is now destroyed

    So reversed() results can only be iterated once unlike sorted(), etc...

    reversed() is an iterator these days:

    l1 = [1, 2, 3]
    rev = reversed( sorted( l1 ) )
    type(rev)
    <class 'list_reverseiterator'>


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Angelico@21:1/5 to python-list@python.org on Mon Sep 4 08:42:41 2023
    On Mon, 4 Sept 2023 at 07:44, Pierre Fortin via Python-list <python-list@python.org> wrote:

    Hi,

    reversed() results are fine until iterated over, after which the
    results are no longer available. This was discovered after using
    something like this:

    rev = reversed( sorted( list ) )
    sr = sum( 1 for _ in rev )
    # rev is now destroyed

    So reversed() results can only be iterated once unlike sorted(), etc...

    reversed() is like iter(), and should be used the same way:

    for item in reversed(list):

    If you want to eagerly construct a full reversed list, instead slice the list:

    list[::-1]

    ChrisA

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)