PEP 322: Reverse Iteration (REVISED, please comment)

Bengt Richter bokr at oz.net
Wed Oct 29 16:01:34 EST 2003


On 28 Oct 2003 10:22:44 -0800, python at rcn.com (Raymond Hettinger) wrote:

>Based on your extensive feedback, PEP 322 has been completely revised.
>The response was strongly positive, but almost everyone preferred
>having a function instead of multiple object methods.  The updated
>proposal is at:
>
>    www.python.org/peps/pep-0322.html
>
>In a nutshell, it proposes a builtin function that greatly simplifies reverse
>iteration.  The core concept is that clarity comes from specifying a
>sequence in a forward direction and then saying, "inreverse()":
>
>    for elem in inreverse(seqn):
>         . . .
>
>Unlike seqn[::-1], this produces a fast iterator instead of a full reversed
>copy.

I'm thinking that a concise way to make a fast iterator from any slice expression
could subsume the inreverse functionality. IOW, a generator slice corresponding
in spirit to generator expressions. E.g., for the inreverse use,

     for elem in seqn'[::-1]:
         . . .

(note the apostrophe in front of the slice notation)

Of course, unlike 'inreverse', you wouldn't be limited to going backwards,

    for oddelem in seqn'[1::2]:
        . . .

Ok, take a deep breath, here comes some more ;-)

How about generator expressions/slices being able to be evaluated in parallel in a 'for' loop
(with '=' instead of 'in' to signify that we're taking elements from each of the
sequences in a tuple and making an intermediate data tuple to unpack for the assignment,
not unpacking the rhs tuple of sequences)? E.g.,

    for oddelem, evenelem = seqn'[1::2], seqn'[0::2]:
        . . .

This seems like a nice generalization that could use any sequences, not just generator slices.
I.e., like tuple assignment, but the 'for' makes the rhs get treated like the above was short for

    for oddelem, evenelem in itertools.izip(seqn'[1::2], seqn'[0::2]):

Note that like tuple assignment, you could unpack as many sequences in parallel as you liked.
(In fact, the single-target case would work too, just by changing 'in' to '=' ;-)
 
If you like generator slices, it might be nice to have bare generator slices too, implicitly
producing a sequence of integers that might make sense in relation to the same notation used
on a sequence. E.g.,

    '[:]               <=> (i for i in xrange(0,sys.maxint,1))
    '[start:stop:step] <=> (i for i in xrange(start,stop,step))
    '[::-1]            <=> (i for i in xrange(-1, -sys.maxint-1, -1))

etc. Thus plain enumerate could be respelled (taking seq via a full generator slice):

    for i, elem = '[:], seq'[:]:
        . . .

and the reversed order, enumerating with indices -1, -2, etc.  would look like

    for i, elem = '[::-1], seq'[::-1]:
        . . .

Too much at once? ;-)
 
>
>Discussions with Guido made it clear that inreverse() will not be extended
>to cover all iterables.  The proposal is about simplicity, expression, and
>performance.  As such, it would be counter-productive to take in a general
>iterable, run it to completion, save the data in memory, and then iterate
>over the data in reverse.
>
The same could apply to seq'[::-1]
I assume seq would be queried for __len__ and __getitem__ when about to create
the generator slice.

Regards,
Bengt Richter




More information about the Python-list mailing list