Permalink
Cannot retrieve contributors at this time
151 lines (111 sloc)
4.19 KB
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| PEP: 281 | |
| Title: Loop Counter Iteration with range and xrange | |
| Version: $Revision$ | |
| Last-Modified: $Date$ | |
| Author: magnus@hetland.org (Magnus Lie Hetland) | |
| Status: Rejected | |
| Type: Standards Track | |
| Content-Type: text/x-rst | |
| Created: 11-Feb-2002 | |
| Python-Version: 2.3 | |
| Post-History: | |
| Abstract | |
| ======== | |
| This PEP describes yet another way of exposing the loop counter in | |
| for-loops. It basically proposes that the functionality of the | |
| function ``indices()`` from :pep:`212` be included in the existing | |
| functions ``range()`` and ``xrange()``. | |
| Pronouncement | |
| ============= | |
| In commenting on :pep:`279`'s ``enumerate()`` function, this PEP's author | |
| offered, "I'm quite happy to have it make :pep:`281` obsolete." | |
| Subsequently, :pep:`279` was accepted into Python 2.3. | |
| On 17 June 2005, the BDFL concurred with it being obsolete and | |
| hereby rejected the PEP. For the record, he found some of the | |
| examples to somewhat jarring in appearance:: | |
| >>> range(range(5), range(10), range(2)) | |
| [5, 7, 9] | |
| Motivation | |
| ========== | |
| It is often desirable to loop over the indices of a sequence. PEP | |
| 212 describes several ways of doing this, including adding a | |
| built-in function called indices, conceptually defined as:: | |
| def indices(sequence): | |
| return range(len(sequence)) | |
| On the assumption that adding functionality to an existing built-in | |
| function may be less intrusive than adding a new built-in function, | |
| this PEP proposes adding this functionality to the existing | |
| functions ``range()`` and ``xrange()``. | |
| Specification | |
| ============= | |
| It is proposed that all three arguments to the built-in functions | |
| ``range()`` and ``xrange()`` are allowed to be objects with a length | |
| (i.e. objects implementing the ``__len__`` method). If an argument | |
| cannot be interpreted as an integer (i.e. it has no ``__int__`` | |
| method), its length will be used instead. | |
| Examples:: | |
| >>> range(range(10)) | |
| [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] | |
| >>> range(range(5), range(10)) | |
| [5, 6, 7, 8, 9] | |
| >>> range(range(5), range(10), range(2)) | |
| [5, 7, 9] | |
| >>> list(xrange(range(10))) | |
| [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] | |
| >>> list(xrange(xrange(10))) | |
| [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] | |
| # Number the lines of a file: | |
| lines = file.readlines() | |
| for num in range(lines): | |
| print num, lines[num] | |
| Alternatives | |
| ============ | |
| A natural alternative to the above specification is allowing | |
| ``xrange()`` to access its arguments in a lazy manner. Thus, instead | |
| of using their length explicitly, ``xrange`` can return one index for | |
| each element of the stop argument until the end is reached. A | |
| similar lazy treatment makes little sense for the start and step | |
| arguments since their length must be calculated before iteration | |
| can begin. (Actually, the length of the step argument isn't needed | |
| until the second element is returned.) | |
| A pseudo-implementation (using only the stop argument, and assuming | |
| that it is iterable) is:: | |
| def xrange(stop): | |
| i = 0 | |
| for x in stop: | |
| yield i | |
| i += 1 | |
| Testing whether to use ``int()`` or lazy iteration could be done by | |
| checking for an ``__iter__`` attribute. (This example assumes the | |
| presence of generators, but could easily have been implemented as a | |
| plain iterator object.) | |
| It may be questionable whether this feature is truly useful, since | |
| one would not be able to access the elements of the iterable object | |
| inside the for loop through indexing. | |
| Example:: | |
| # Printing the numbers of the lines of a file: | |
| for num in range(file): | |
| print num # The line itself is not accessible | |
| A more controversial alternative (to deal with this) would be to | |
| let ``range()`` behave like the function ``irange()`` of :pep:`212` when | |
| supplied with a sequence. | |
| Example:: | |
| >>> range(5) | |
| [0, 1, 2, 3, 4] | |
| >>> range('abcde') | |
| [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e')] | |
| Backwards Compatibility | |
| ======================= | |
| The proposal could cause backwards incompatibilities if arguments | |
| are used which implement both ``__int__`` and ``__len__`` (or ``__iter__`` in | |
| the case of lazy iteration with ``xrange``). The author does not | |
| believe that this is a significant problem. | |
| Copyright | |
| ========= | |
| This document has been placed in the public domain. | |
| .. | |
| Local Variables: | |
| mode: indented-text | |
| indent-tabs-mode: nil | |
| fill-column: 70 | |
| End: |