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 \[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/dev/peps/pep-0212/

Copyright
=========

This document has been placed in the public domain.

.. Local Variables: mode: indented-text indent-tabs-mode: nil
fill-column: 70 End:
