PEP: 212 Title: Loop Counter Iteration Author: Peter Schneider-Kamp
<nowonder@nowonder.de> Status: Rejected Type: Standards Track
Content-Type: text/x-rst Created: 22-Aug-2000 Python-Version: 2.1
Post-History:

Rejection Notice

This PEP has been rejected. enumerate(), introduced in PEP 279, covers
the use-case proposed in this PEP, and the PEP author has been
unreachable.

Introduction

This PEP describes the often proposed feature of exposing the loop
counter in for-loops. This PEP tracks the status and ownership of this
feature. It contains a description of the feature and outlines changes
necessary to support the feature. This PEP summarizes discussions held
in mailing list forums, and provides URLs for further information, where
appropriate. The CVS revision history of this file contains the
definitive historical record.

Motivation

Standard for-loops in Python iterate over the elements of a sequence[1].
Often it is desirable to loop over the indices or both the elements and
the indices instead.

The common idioms used to accomplish this are unintuitive. This PEP
proposes two different ways of exposing the indices.

Loop counter iteration

The current idiom for looping over the indices makes use of the built-in
range function:

    for i in range(len(sequence)):
        # work with index i

Looping over both elements and indices can be achieved either by the old
idiom or by using the new zip built-in function[2]:

    for i in range(len(sequence)):
        e = sequence[i]
        # work with index i and element e

or:

    for i, e in zip(range(len(sequence)), sequence):
       # work with index i and element e

The Proposed Solutions

There are three solutions that have been discussed. One adds a
non-reserved keyword, the other adds two built-in functions. A third
solution adds methods to sequence objects.

Non-reserved keyword indexing

This solution would extend the syntax of the for-loop by adding an
optional <variable> indexing clause which can also be used instead of
the <variable> in clause.

Looping over the indices of a sequence would thus become:

    for i indexing sequence:
        # work with index i

Looping over both indices and elements would similarly be:

    for i indexing e in sequence:
        # work with index i and element e

Built-in functions indices and irange

This solution adds two built-in functions indices and irange. The
semantics of these can be described as follows:

    def indices(sequence):
        return range(len(sequence))

    def irange(sequence):
        return zip(range(len(sequence)), sequence)

These functions could be implemented either eagerly or lazily and should
be easy to extend in order to accept more than one sequence argument.

The use of these functions would simplify the idioms for looping over
the indices and over both elements and indices:

    for i in indices(sequence):
        # work with index i

    for i, e in irange(sequence):
        # work with index i and element e

Methods for sequence objects

This solution proposes the addition of indices, items and values methods
to sequences, which enable looping over indices only, both indices and
elements, and elements only respectively.

This would immensely simplify the idioms for looping over indices and
for looping over both elements and indices:

    for i in sequence.indices():
        # work with index i

    for i, e in sequence.items():
        # work with index i and element e

Additionally it would allow to do looping over the elements of sequences
and dictionaries in a consistent way:

    for e in sequence_or_dict.values():
        # do something with element e

Implementations

For all three solutions some more or less rough patches exist as patches
at SourceForge:

-   for i indexing a in l: exposing the for-loop counter[3]
-   add indices() and irange() to built-ins[4]
-   add items() method to listobject[5]

All of them have been pronounced on and rejected by the BDFL.

Note that the indexing keyword is only a NAME in the grammar and so does
not hinder the general use of indexing.

Backward Compatibility Issues

As no keywords are added and the semantics of existing code remains
unchanged, all three solutions can be implemented without breaking
existing code.

Copyright

This document has been placed in the public domain.

References

[1] http://docs.python.org/reference/compound_stmts.html#for

[2] Lockstep Iteration, PEP 201

[3] http://sourceforge.net/patch/download.php?id=101138

[4] http://sourceforge.net/patch/download.php?id=101129

[5] http://sourceforge.net/patch/download.php?id=101178