183 lines
4.9 KiB
ReStructuredText
183 lines
4.9 KiB
ReStructuredText
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
|