CINXE.COM
PEP 212 – Loop Counter Iteration | peps.python.org
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="color-scheme" content="light dark"> <title>PEP 212 – Loop Counter Iteration | peps.python.org</title> <link rel="shortcut icon" href="../_static/py.png"> <link rel="canonical" href="https://peps.python.org/pep-0212/"> <link rel="stylesheet" href="../_static/style.css" type="text/css"> <link rel="stylesheet" href="../_static/mq.css" type="text/css"> <link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light"> <link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark"> <link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss"> <meta property="og:title" content='PEP 212 – Loop Counter Iteration | peps.python.org'> <meta property="og:description" content="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 PE..."> <meta property="og:type" content="website"> <meta property="og:url" content="https://peps.python.org/pep-0212/"> <meta property="og:site_name" content="Python Enhancement Proposals (PEPs)"> <meta property="og:image" content="https://peps.python.org/_static/og-image.png"> <meta property="og:image:alt" content="Python PEPs"> <meta property="og:image:width" content="200"> <meta property="og:image:height" content="200"> <meta name="description" content="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 PE..."> <meta name="theme-color" content="#3776ab"> </head> <body> <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all"> <title>Following system colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="9"></circle> <path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path> </svg> </symbol> <symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all"> <title>Selected dark colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path stroke="none" d="M0 0h24v24H0z" fill="none"></path> <path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path> </svg> </symbol> <symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all"> <title>Selected light colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="5"></circle> <line x1="12" y1="1" x2="12" y2="3"></line> <line x1="12" y1="21" x2="12" y2="23"></line> <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line> <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line> <line x1="1" y1="12" x2="3" y2="12"></line> <line x1="21" y1="12" x2="23" y2="12"></line> <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line> <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line> </svg> </symbol> </svg> <script> document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto" </script> <section id="pep-page-section"> <header> <h1>Python Enhancement Proposals</h1> <ul class="breadcrumbs"> <li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> » </li> <li><a href="../pep-0000/">PEP Index</a> » </li> <li>PEP 212</li> </ul> <button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())"> <svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg> <svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg> <svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg> <span class="visually-hidden">Toggle light / dark / auto colour theme</span> </button> </header> <article> <section id="pep-content"> <h1 class="page-title">PEP 212 – Loop Counter Iteration</h1> <dl class="rfc2822 field-list simple"> <dt class="field-odd">Author<span class="colon">:</span></dt> <dd class="field-odd">Peter Schneider-Kamp <nowonder at nowonder.de></dd> <dt class="field-even">Status<span class="colon">:</span></dt> <dd class="field-even"><abbr title="Formally declined and will not be accepted">Rejected</abbr></dd> <dt class="field-odd">Type<span class="colon">:</span></dt> <dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd> <dt class="field-even">Created<span class="colon">:</span></dt> <dd class="field-even">22-Aug-2000</dd> <dt class="field-odd">Python-Version<span class="colon">:</span></dt> <dd class="field-odd">2.1</dd> <dt class="field-even">Post-History<span class="colon">:</span></dt> <dd class="field-even"><p></p></dd> </dl> <hr class="docutils" /> <section id="contents"> <details><summary>Table of Contents</summary><ul class="simple"> <li><a class="reference internal" href="#rejection-notice">Rejection Notice</a></li> <li><a class="reference internal" href="#introduction">Introduction</a></li> <li><a class="reference internal" href="#motivation">Motivation</a></li> <li><a class="reference internal" href="#loop-counter-iteration">Loop counter iteration</a></li> <li><a class="reference internal" href="#the-proposed-solutions">The Proposed Solutions</a></li> <li><a class="reference internal" href="#non-reserved-keyword-indexing">Non-reserved keyword <code class="docutils literal notranslate"><span class="pre">indexing</span></code></a></li> <li><a class="reference internal" href="#built-in-functions-indices-and-irange">Built-in functions <code class="docutils literal notranslate"><span class="pre">indices</span></code> and <code class="docutils literal notranslate"><span class="pre">irange</span></code></a></li> <li><a class="reference internal" href="#methods-for-sequence-objects">Methods for sequence objects</a></li> <li><a class="reference internal" href="#implementations">Implementations</a></li> <li><a class="reference internal" href="#backward-compatibility-issues">Backward Compatibility Issues</a></li> <li><a class="reference internal" href="#copyright">Copyright</a></li> <li><a class="reference internal" href="#references">References</a></li> </ul> </details></section> <section id="rejection-notice"> <h2><a class="toc-backref" href="#rejection-notice" role="doc-backlink">Rejection Notice</a></h2> <p>This PEP has been rejected. <code class="docutils literal notranslate"><span class="pre">enumerate()</span></code>, introduced in <a class="pep reference internal" href="../pep-0279/" title="PEP 279 – The enumerate() built-in function">PEP 279</a>, covers the use-case proposed in this PEP, and the PEP author has been unreachable.</p> </section> <section id="introduction"> <h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2> <p>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.</p> </section> <section id="motivation"> <h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2> <p>Standard for-loops in Python iterate over the elements of a sequence <a class="footnote-reference brackets" href="#id6" id="id1">[1]</a>. Often it is desirable to loop over the indices or both the elements and the indices instead.</p> <p>The common idioms used to accomplish this are unintuitive. This PEP proposes two different ways of exposing the indices.</p> </section> <section id="loop-counter-iteration"> <h2><a class="toc-backref" href="#loop-counter-iteration" role="doc-backlink">Loop counter iteration</a></h2> <p>The current idiom for looping over the indices makes use of the built-in <code class="docutils literal notranslate"><span class="pre">range</span></code> function:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">sequence</span><span class="p">)):</span> <span class="c1"># work with index i</span> </pre></div> </div> <p>Looping over both elements and indices can be achieved either by the old idiom or by using the new <code class="docutils literal notranslate"><span class="pre">zip</span></code> built-in function <a class="footnote-reference brackets" href="#id7" id="id2">[2]</a>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">sequence</span><span class="p">)):</span> <span class="n">e</span> <span class="o">=</span> <span class="n">sequence</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="c1"># work with index i and element e</span> </pre></div> </div> <p>or:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">e</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">sequence</span><span class="p">)),</span> <span class="n">sequence</span><span class="p">):</span> <span class="c1"># work with index i and element e</span> </pre></div> </div> </section> <section id="the-proposed-solutions"> <h2><a class="toc-backref" href="#the-proposed-solutions" role="doc-backlink">The Proposed Solutions</a></h2> <p>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.</p> </section> <section id="non-reserved-keyword-indexing"> <h2><a class="toc-backref" href="#non-reserved-keyword-indexing" role="doc-backlink">Non-reserved keyword <code class="docutils literal notranslate"><span class="pre">indexing</span></code></a></h2> <p>This solution would extend the syntax of the for-loop by adding an optional <code class="docutils literal notranslate"><span class="pre"><variable></span> <span class="pre">indexing</span></code> clause which can also be used instead of the <code class="docutils literal notranslate"><span class="pre"><variable></span> <span class="pre">in</span></code> clause.</p> <p>Looping over the indices of a sequence would thus become:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">i</span> <span class="n">indexing</span> <span class="n">sequence</span><span class="p">:</span> <span class="c1"># work with index i</span> </pre></div> </div> <p>Looping over both indices and elements would similarly be:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">i</span> <span class="n">indexing</span> <span class="n">e</span> <span class="ow">in</span> <span class="n">sequence</span><span class="p">:</span> <span class="c1"># work with index i and element e</span> </pre></div> </div> </section> <section id="built-in-functions-indices-and-irange"> <h2><a class="toc-backref" href="#built-in-functions-indices-and-irange" role="doc-backlink">Built-in functions <code class="docutils literal notranslate"><span class="pre">indices</span></code> and <code class="docutils literal notranslate"><span class="pre">irange</span></code></a></h2> <p>This solution adds two built-in functions <code class="docutils literal notranslate"><span class="pre">indices</span></code> and <code class="docutils literal notranslate"><span class="pre">irange</span></code>. The semantics of these can be described as follows:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">indices</span><span class="p">(</span><span class="n">sequence</span><span class="p">):</span> <span class="k">return</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">sequence</span><span class="p">))</span> <span class="k">def</span> <span class="nf">irange</span><span class="p">(</span><span class="n">sequence</span><span class="p">):</span> <span class="k">return</span> <span class="nb">zip</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">sequence</span><span class="p">)),</span> <span class="n">sequence</span><span class="p">)</span> </pre></div> </div> <p>These functions could be implemented either eagerly or lazily and should be easy to extend in order to accept more than one sequence argument.</p> <p>The use of these functions would simplify the idioms for looping over the indices and over both elements and indices:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">indices</span><span class="p">(</span><span class="n">sequence</span><span class="p">):</span> <span class="c1"># work with index i</span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">e</span> <span class="ow">in</span> <span class="n">irange</span><span class="p">(</span><span class="n">sequence</span><span class="p">):</span> <span class="c1"># work with index i and element e</span> </pre></div> </div> </section> <section id="methods-for-sequence-objects"> <h2><a class="toc-backref" href="#methods-for-sequence-objects" role="doc-backlink">Methods for sequence objects</a></h2> <p>This solution proposes the addition of <code class="docutils literal notranslate"><span class="pre">indices</span></code>, <code class="docutils literal notranslate"><span class="pre">items</span></code> and <code class="docutils literal notranslate"><span class="pre">values</span></code> methods to sequences, which enable looping over indices only, both indices and elements, and elements only respectively.</p> <p>This would immensely simplify the idioms for looping over indices and for looping over both elements and indices:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">sequence</span><span class="o">.</span><span class="n">indices</span><span class="p">():</span> <span class="c1"># work with index i</span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">e</span> <span class="ow">in</span> <span class="n">sequence</span><span class="o">.</span><span class="n">items</span><span class="p">():</span> <span class="c1"># work with index i and element e</span> </pre></div> </div> <p>Additionally it would allow to do looping over the elements of sequences and dictionaries in a consistent way:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">e</span> <span class="ow">in</span> <span class="n">sequence_or_dict</span><span class="o">.</span><span class="n">values</span><span class="p">():</span> <span class="c1"># do something with element e</span> </pre></div> </div> </section> <section id="implementations"> <h2><a class="toc-backref" href="#implementations" role="doc-backlink">Implementations</a></h2> <p>For all three solutions some more or less rough patches exist as patches at SourceForge:</p> <ul class="simple"> <li><code class="docutils literal notranslate"><span class="pre">for</span> <span class="pre">i</span> <span class="pre">indexing</span> <span class="pre">a</span> <span class="pre">in</span> <span class="pre">l</span></code>: exposing the for-loop counter <a class="footnote-reference brackets" href="#id8" id="id3">[3]</a></li> <li>add <code class="docutils literal notranslate"><span class="pre">indices()</span></code> and <code class="docutils literal notranslate"><span class="pre">irange()</span></code> to built-ins <a class="footnote-reference brackets" href="#id9" id="id4">[4]</a></li> <li>add <code class="docutils literal notranslate"><span class="pre">items()</span></code> method to listobject <a class="footnote-reference brackets" href="#id10" id="id5">[5]</a></li> </ul> <p>All of them have been pronounced on and rejected by the BDFL.</p> <p>Note that the <code class="docutils literal notranslate"><span class="pre">indexing</span></code> keyword is only a <code class="docutils literal notranslate"><span class="pre">NAME</span></code> in the grammar and so does not hinder the general use of <code class="docutils literal notranslate"><span class="pre">indexing</span></code>.</p> </section> <section id="backward-compatibility-issues"> <h2><a class="toc-backref" href="#backward-compatibility-issues" role="doc-backlink">Backward Compatibility Issues</a></h2> <p>As no keywords are added and the semantics of existing code remains unchanged, all three solutions can be implemented without breaking existing code.</p> </section> <section id="copyright"> <h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2> <p>This document has been placed in the public domain.</p> </section> <section id="references"> <h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2> <aside class="footnote-list brackets"> <aside class="footnote brackets" id="id6" role="doc-footnote"> <dt class="label" id="id6">[<a href="#id1">1</a>]</dt> <dd><a class="reference external" href="http://docs.python.org/reference/compound_stmts.html#for">http://docs.python.org/reference/compound_stmts.html#for</a></aside> <aside class="footnote brackets" id="id7" role="doc-footnote"> <dt class="label" id="id7">[<a href="#id2">2</a>]</dt> <dd>Lockstep Iteration, <a class="pep reference internal" href="../pep-0201/" title="PEP 201 – Lockstep Iteration">PEP 201</a></aside> <aside class="footnote brackets" id="id8" role="doc-footnote"> <dt class="label" id="id8">[<a href="#id3">3</a>]</dt> <dd><a class="reference external" href="http://sourceforge.net/patch/download.php?id=101138">http://sourceforge.net/patch/download.php?id=101138</a></aside> <aside class="footnote brackets" id="id9" role="doc-footnote"> <dt class="label" id="id9">[<a href="#id4">4</a>]</dt> <dd><a class="reference external" href="http://sourceforge.net/patch/download.php?id=101129">http://sourceforge.net/patch/download.php?id=101129</a></aside> <aside class="footnote brackets" id="id10" role="doc-footnote"> <dt class="label" id="id10">[<a href="#id5">5</a>]</dt> <dd><a class="reference external" href="http://sourceforge.net/patch/download.php?id=101178">http://sourceforge.net/patch/download.php?id=101178</a></aside> </aside> </section> </section> <hr class="docutils" /> <p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0212.rst">https://github.com/python/peps/blob/main/peps/pep-0212.rst</a></p> <p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0212.rst">2023-09-09 17:39:29 GMT</a></p> </article> <nav id="pep-sidebar"> <h2>Contents</h2> <ul> <li><a class="reference internal" href="#rejection-notice">Rejection Notice</a></li> <li><a class="reference internal" href="#introduction">Introduction</a></li> <li><a class="reference internal" href="#motivation">Motivation</a></li> <li><a class="reference internal" href="#loop-counter-iteration">Loop counter iteration</a></li> <li><a class="reference internal" href="#the-proposed-solutions">The Proposed Solutions</a></li> <li><a class="reference internal" href="#non-reserved-keyword-indexing">Non-reserved keyword <code class="docutils literal notranslate"><span class="pre">indexing</span></code></a></li> <li><a class="reference internal" href="#built-in-functions-indices-and-irange">Built-in functions <code class="docutils literal notranslate"><span class="pre">indices</span></code> and <code class="docutils literal notranslate"><span class="pre">irange</span></code></a></li> <li><a class="reference internal" href="#methods-for-sequence-objects">Methods for sequence objects</a></li> <li><a class="reference internal" href="#implementations">Implementations</a></li> <li><a class="reference internal" href="#backward-compatibility-issues">Backward Compatibility Issues</a></li> <li><a class="reference internal" href="#copyright">Copyright</a></li> <li><a class="reference internal" href="#references">References</a></li> </ul> <br> <a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0212.rst">Page Source (GitHub)</a> </nav> </section> <script src="../_static/colour_scheme.js"></script> <script src="../_static/wrap_tables.js"></script> <script src="../_static/sticky_banner.js"></script> </body> </html>