[Python-checkins] python/nondist/peps pep-0000.txt, 1.255,
1.256 pep-0322.txt, 1.5, 1.6
rhettinger at users.sourceforge.net
rhettinger at users.sourceforge.net
Tue Oct 28 05:16:35 EST 2003
Update of /cvsroot/python/python/nondist/peps
In directory sc8-pr-cvs1:/tmp/cvs-serv12216
Modified Files:
pep-0000.txt pep-0322.txt
Log Message:
Update the reverse iteration pep to reflect comments from comp.lang.python,
from Guido, and from some on python-dev.
Index: pep-0000.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/peps/pep-0000.txt,v
retrieving revision 1.255
retrieving revision 1.256
diff -C2 -d -r1.255 -r1.256
*** pep-0000.txt 27 Oct 2003 15:01:08 -0000 1.255
--- pep-0000.txt 28 Oct 2003 10:16:31 -0000 1.256
***************
*** 119,123 ****
S 319 Python Synchronize/Asynchronize Block Pelletier
S 321 Date/Time Parsing and Formatting Kuchling
! S 322 Reverse Iteration Methods Hettinger
S 323 Copyable Iterators Martelli
S 754 IEEE 754 Floating Point Special Values Warnes
--- 119,123 ----
S 319 Python Synchronize/Asynchronize Block Pelletier
S 321 Date/Time Parsing and Formatting Kuchling
! S 322 Reverse Iteration Hettinger
S 323 Copyable Iterators Martelli
S 754 IEEE 754 Floating Point Special Values Warnes
***************
*** 338,342 ****
I 320 Python 2.4 Release Schedule Warsaw
S 321 Date/Time Parsing and Formatting Kuchling
! S 322 Reverse Iteration Methods Hettinger
SR 666 Reject Foolish Indentation Creighton
S 754 IEEE 754 Floating Point Special Values Warnes
--- 338,342 ----
I 320 Python 2.4 Release Schedule Warsaw
S 321 Date/Time Parsing and Formatting Kuchling
! S 322 Reverse Iteration Hettinger
SR 666 Reject Foolish Indentation Creighton
S 754 IEEE 754 Floating Point Special Values Warnes
Index: pep-0322.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/peps/pep-0322.txt,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** pep-0322.txt 28 Sep 2003 02:43:37 -0000 1.5
--- pep-0322.txt 28 Oct 2003 10:16:32 -0000 1.6
***************
*** 1,4 ****
PEP: 322
! Title: Reverse Iteration Methods
Version: $Revision$
Last-Modified: $Date$
--- 1,4 ----
PEP: 322
! Title: Reverse Iteration
Version: $Revision$
Last-Modified: $Date$
***************
*** 15,20 ****
========
! This proposal is to extend the API of several sequence types
! to include a method for iterating over the sequence in reverse.
--- 15,20 ----
========
! This proposal is to add a builtin function to support reverse
! iteration over sequences.
***************
*** 47,66 ****
========
! Add a method called *iterreverse()* to sequence objects that can
! benefit from it. The above examples then simplify to::
! for i in xrange(n).iterreverse():
print seqn[i]
::
! for elem in seqn.iterreverse():
print elem
! The new protocol would be applied to lists, tuples, strings, and
! xrange objects. It would not apply to unordered collections like
! dicts and sets.
! No language syntax changes are needed.
--- 47,81 ----
========
! Add a builtin function called *inreverse()* that makes a reverse
! iterator over sequence objects that support __getitem__() and
! __len__().
! The above examples then simplify to::
!
! for i in inreverse(xrange(n)):
print seqn[i]
::
! for elem in inreverse(seqn):
print elem
! The core idea is that the clearest, least error-prone way of specifying
! reverse iteration is to specify it in a forward direction and then say
! *inreverse*.
! The implementation could be as simple as::
!
! def inreverse(x):
! i = len(x)
! while i > 0:
! i -= 1
! yield x[i]
!
! If *x* is a mapping, the implementation should return a ValueError with
! a message noting that reverse iteration is undefined for mappings.
!
! No language syntax changes are needed. The proposal is fully backwards
! compatible.
***************
*** 68,91 ****
========================
- * *iterbackwards* -- like iteritems() but somewhat long
* *backwards* -- more pithy, less explicit
* *ireverse* -- reminiscent of imap(), izip(), and ifilter()
! Other Issues
! ============
! * Should *tuple* objects be included? In the past, they have been
! denied some list like behaviors such as count() and index(). I
! prefer that it be included.
! * Should *file* objects be included? Implementing reverse iteration
! may not be easy though it would be useful on occasion. I think
! this one should be skipped.
! * Should *enumerate* objects be included? They can provide reverse
! iteration only when the underlying sequences support *__len__*
! and reverse iteration. I think this can be saved for another
! day if the need arises.
--- 83,102 ----
========================
* *backwards* -- more pithy, less explicit
* *ireverse* -- reminiscent of imap(), izip(), and ifilter()
! Custom Reverse
! ==============
! Objects may optionally provide an *__inreverse__* method that returns
! a custom reverse iterator.
! This allows reverse() to be applied to objects that do not have
! __getitem__() and __len__() but still have some useful way of
! providing reverse iteration.
! Using this protocol, enumerate() can be extended to support reversal
! whenever the underlying iterator supports it also.
***************
*** 102,138 ****
. . .
! The application dictates the need to run exit handlers in the
! reverse order they were built. The ``while alist: alist.pop()``
! form is readable and clean; however, it would be slightly faster
! and clearer with::
!
! for func, target, kargs in _exithandlers.iterreverse():
! . . .
! del _exithandlers
!
! Note, if the order of deletion is important, then the first form
! is still needed.
!
! * difflib.get_close_matches() uses::
!
! result.sort() # Retain only the best n.
! result = result[-n:] # Move best-scorer to head of list.
! result.reverse() # Strip scores.
! return [x for score, x in result]
!
! The need for reverse iteration arises from a requirement to return
! a portion of a sort in an order opposite of the sort criterion. The
! list comprehension is incidental (the third step of a Schwartzian
! transform). This particular use case can met with extended slicing,
! but the code is somewhat unattractive, hard to visually verify,
! and difficult for beginners to construct::
!
! result.sort()
! return [x for score, x in result[:-n-1:-1]]
!
! The proposed form is much easier to construct and verify::
!
! result.sort()
! return [x for score, x in result[-n:].iterreverse()]
* heapq.heapify() uses ``for i in xrange(n//2 - 1, -1, -1)`` because
--- 113,118 ----
. . .
! In this application popping is required, so the new function would
! not help.
* heapq.heapify() uses ``for i in xrange(n//2 - 1, -1, -1)`` because
***************
*** 161,166 ****
be run in a forward direction but is less intuitive and rarely
presented that way in literature. The replacement code
! ``for i in xrange(1, len(x)).iterreverse()`` is much easier
! to mentally verify.
* rfc822.Message.__delitem__() uses::
--- 141,146 ----
be run in a forward direction but is less intuitive and rarely
presented that way in literature. The replacement code
! ``for i in inreverse(xrange(1, len(x)))`` is much easier
! to verify visually.
* rfc822.Message.__delitem__() uses::
***************
*** 174,203 ****
! Alternative Ideas
! =================
!
! * Add a builtin function, *riter()* which calls a magic method,
! *__riter__*. I see this as more overhead for no additional benefit.
!
! * Several variants were submitted that provided fallback behavior
! when *__riter__* is not defined:
!
! - fallback to: ``for i in xrange(len(obj)-1,-1,-1): yield obj[i]``
! - fallback to: ``for i in itertools.count(): yield obj[-i]``
! - fallback to: ``tmp=list(obj); tmp.reverse(); return iter(tmp)``
!
! All of these attempt to save implementing some object methods at the
! expense of adding a new builtin function and of creating a new magic
! method name.
!
! The approaches using *__getitem__()* are slower than using a custom
! method for each object. Also, the *__getitem__()* variants produce
! bizarre results when applied to mappings.
!
! All of the variants crash when applied to an infinite iterator.
! The last variant can invisibly slip into a low performance mode
! (in terms of time and memory) which could be made more visible with
! an explicit ``ro=list(obj); ro.reverse()``.
--- 154,167 ----
! Rejected Alternative
! ====================
! Several variants were submitted that attempted to apply inreverse()
! to all iterables by running the iterable to completion, saving the
! results, and then returning a reverse iterator over the results.
! While satisfying some notions of full generality, running the input
! to the end is contrary to the purpose of using iterators
! in the first place. Also, a small disaster ensues if the underlying
! iterator is infinite.
More information about the Python-checkins
mailing list