148 lines
4.2 KiB
Plaintext
148 lines
4.2 KiB
Plaintext
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
|
||
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 [1] 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.
|
||
|
||
|
||
References and Footnotes
|
||
|
||
[1] PEP 212, Loop Counter Iteration
|
||
http://www.python.org/peps/pep-0212.html
|
||
|
||
|
||
Copyright
|
||
|
||
This document has been placed in the public domain.
|
||
|
||
|
||
|
||
Local Variables:
|
||
mode: indented-text
|
||
indent-tabs-mode: nil
|
||
fill-column: 70
|
||
End:
|