[Python-checkins] python/nondist/peps pep-0322.txt,1.9,1.10
rhettinger at users.sourceforge.net
rhettinger at users.sourceforge.net
Thu Oct 30 02:41:22 EST 2003
Update of /cvsroot/python/python/nondist/peps
In directory sc8-pr-cvs1:/tmp/cvs-serv29134
Modified Files:
pep-0322.txt
Log Message:
Update PEP based on discussion on comp.lang.python:
* reversed() is being preferred to ireverse() as the best name.
* the sample implementation now shows a check for a custom reverse
method and a guard against being applied to a mapping.
* added sample output for enumerate.__reversed__ to show an example of
how a custom reverse method would work
* explained why the function is proposed as a builtin.
* expanded a couple for the real world use cases to show what the
replacement code would look like.
* improved markup so that the function names get italicized.
Index: pep-0322.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/peps/pep-0322.txt,v
retrieving revision 1.9
retrieving revision 1.10
diff -C2 -d -r1.9 -r1.10
*** pep-0322.txt 28 Oct 2003 22:39:22 -0000 1.9
--- pep-0322.txt 30 Oct 2003 07:41:20 -0000 1.10
***************
*** 47,51 ****
========
! Add a builtin function called *ireverse()* that makes a reverse
iterator over sequence objects that support __getitem__() and
__len__().
--- 47,51 ----
========
! Add a builtin function called *reversed()* that makes a reverse
iterator over sequence objects that support __getitem__() and
__len__().
***************
*** 53,71 ****
The above examples then simplify to::
! for i in ireverse(xrange(n)):
print seqn[i]
::
! for elem in ireverse(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
! *ireverse*.
The implementation could be as simple as::
! def ireverse(x):
i = len(x)
while i > 0:
--- 53,77 ----
The above examples then simplify to::
! for i in reversed(xrange(n)):
print seqn[i]
::
! for elem in reversed(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
! *reversed*.
The implementation could be as simple as::
! def reversed(x):
! try:
! return x.__reversed__()
! except AttributeError:
! pass
! if hasattr(x, "has_key"):
! raise ValueError("mappings do not support reverse iteration")
i = len(x)
while i > 0:
***************
*** 73,79 ****
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.
--- 79,82 ----
***************
*** 83,87 ****
========================
! * *backwards* -- more pithy, less explicit
* *inreverse* -- no one seems to like this one except me
--- 86,90 ----
========================
! * *ireverse* -- uses the itertools naming convention
* *inreverse* -- no one seems to like this one except me
***************
*** 93,105 ****
==============
! Objects may optionally provide an *__ireverse__* 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.
--- 96,111 ----
==============
! Objects may optionally provide a *__reversed__* 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.
! For example, using this protocol, *enumerate()* can be extended to
! support reversal whenever the underlying iterator supports it also::
!
! >>> list(reversed(enumerate("abc")))
! [(2, 'c'), (1, 'b'), (0, 'a')]
***************
*** 124,127 ****
--- 130,135 ----
possible; however, that would complicate the rest of the heap code
which iterates over the underlying list in the opposite direction.
+ The replacement code ``for i in reversed(xrange(n//2))`` makes
+ clear the range covered and how many iterations it takes.
* mhlib.test() uses::
***************
*** 144,148 ****
be run in a forward direction but is less intuitive and rarely
presented that way in literature. The replacement code
! ``for i in ireverse(xrange(1, len(x)))`` is much easier
to verify visually.
--- 152,156 ----
be run in a forward direction but is less intuitive and rarely
presented that way in literature. The replacement code
! ``for i in reversed(xrange(1, len(x)))`` is much easier
to verify visually.
***************
*** 161,175 ****
A simpler, but limited alternative is to create a builtin that takes
! the same arguments as range() but returns a reverse iterator over the
! range. The idea is that much of the benefit of ireverse() comes
reducing the intellectual effort it takes to express the arguments for
[x]range() when going backwards. A good name is needed for this
! alternative -- revrange() is cleanest so far.
! Rejected Alternative
! ====================
! Several variants were submitted that attempted to apply ireverse()
to all iterables by running the iterable to completion, saving the
results, and then returning a reverse iterator over the results.
--- 169,183 ----
A simpler, but limited alternative is to create a builtin that takes
! the same arguments as *range()* but returns a reverse iterator over the
! range. The idea is that much of the benefit of *reversed()* comes
reducing the intellectual effort it takes to express the arguments for
[x]range() when going backwards. A good name is needed for this
! alternative -- *revrange()* is cleanest so far.
! Rejected Alternatives
! =====================
! Several variants were submitted that attempted to apply *reversed()*
to all iterables by running the iterable to completion, saving the
results, and then returning a reverse iterator over the results.
***************
*** 178,181 ****
--- 186,197 ----
in the first place. Also, a small disaster ensues if the underlying
iterator is infinite.
+
+ Putting the function in another module or attaching it to a type object
+ is not being considered. Like its cousins, *zip()* and *enumerate()*,
+ the function needs to be directly accessible in daily programming. Each
+ solves a basic looping problem: lock-step iteration, loop counting, and
+ reverse iteration. Requiring some form of dotted access would interfere
+ with their simplicity, daily utility, and accessibility. They are core
+ looping constructs, independent of any one application domain.
More information about the Python-checkins
mailing list