peps/pep-3136/index.html

565 lines
42 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!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 3136 Labeled break and continue | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-3136/">
<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 3136 Labeled break and continue | peps.python.org'>
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-3136/">
<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="Python Enhancement Proposals (PEPs)">
<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> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 3136</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 3136 Labeled break and continue</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Matt Chisholm &lt;matt-python&#32;&#97;t&#32;theory.org&gt;</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">30-Jun-2007</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">3.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="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a><ul>
<li><a class="reference internal" href="#other-languages">Other languages</a></li>
</ul>
</li>
<li><a class="reference internal" href="#what-this-pep-is-not">What this PEP is not</a></li>
<li><a class="reference internal" href="#specification">Specification</a><ul>
<li><a class="reference internal" href="#proposal-a-explicit-labels">Proposal A - Explicit labels</a></li>
<li><a class="reference internal" href="#proposal-b-numeric-break-continue">Proposal B - Numeric break &amp; continue</a></li>
<li><a class="reference internal" href="#proposal-c-the-reduplicative-method">Proposal C - The reduplicative method</a></li>
<li><a class="reference internal" href="#proposal-d-explicit-iterators">Proposal D - Explicit iterators</a></li>
<li><a class="reference internal" href="#proposal-e-explicit-iterators-and-iterator-methods">Proposal E - Explicit iterators and iterator methods</a></li>
</ul>
</li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#footnotes">Footnotes</a></li>
<li><a class="reference internal" href="#resources">Resources</a></li>
<li><a class="reference internal" href="#copyright">Copyright</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 is rejected.
See <a class="reference external" href="https://mail.python.org/pipermail/python-3000/2007-July/008663.html">https://mail.python.org/pipermail/python-3000/2007-July/008663.html</a>.</p>
</section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>This PEP proposes support for labels in Pythons <code class="docutils literal notranslate"><span class="pre">break</span></code> and
<code class="docutils literal notranslate"><span class="pre">continue</span></code> statements. It is inspired by labeled <code class="docutils literal notranslate"><span class="pre">break</span></code> and
<code class="docutils literal notranslate"><span class="pre">continue</span></code> in other languages, and the authors own infrequent but
persistent need for such a feature.</p>
</section>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>The <code class="docutils literal notranslate"><span class="pre">break</span></code> statement allows the programmer to terminate a loop
early, and the <code class="docutils literal notranslate"><span class="pre">continue</span></code> statement allows the programmer to move to
the next iteration of a loop early. In Python currently, <code class="docutils literal notranslate"><span class="pre">break</span></code>
and <code class="docutils literal notranslate"><span class="pre">continue</span></code> can apply only to the innermost enclosing loop.</p>
<p>Adding support for labels to the <code class="docutils literal notranslate"><span class="pre">break</span></code> and <code class="docutils literal notranslate"><span class="pre">continue</span></code> statements
is a logical extension to the existing behavior of the <code class="docutils literal notranslate"><span class="pre">break</span></code> and
<code class="docutils literal notranslate"><span class="pre">continue</span></code> statements. Labeled <code class="docutils literal notranslate"><span class="pre">break</span></code> and <code class="docutils literal notranslate"><span class="pre">continue</span></code> can
improve the readability and flexibility of complex code which uses
nested loops.</p>
<p>For brevitys sake, the examples and discussion in this PEP usually
refers to the <code class="docutils literal notranslate"><span class="pre">break</span></code> statement. However, all of the examples and
motivations apply equally to labeled <code class="docutils literal notranslate"><span class="pre">continue</span></code>.</p>
</section>
<section id="motivation">
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
<p>If the programmer wishes to move to the next iteration of an outer
enclosing loop, or terminate multiple loops at once, he or she has a
few less-than elegant options.</p>
<p>Heres one common way of imitating labeled <code class="docutils literal notranslate"><span class="pre">break</span></code> in Python (For
this and future examples, <code class="docutils literal notranslate"><span class="pre">...</span></code> denotes an arbitrary number of
intervening lines of code):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">a_list</span><span class="p">:</span>
<span class="n">time_to_break_out_of_a</span> <span class="o">=</span> <span class="kc">False</span>
<span class="o">...</span>
<span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">b_list</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">if</span> <span class="n">condition_one</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
<span class="k">break</span>
<span class="o">...</span>
<span class="k">if</span> <span class="n">condition_two</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
<span class="n">time_to_break_out_of_a</span> <span class="o">=</span> <span class="kc">True</span>
<span class="k">break</span>
<span class="o">...</span>
<span class="k">if</span> <span class="n">time_to_break_out_of_a</span><span class="p">:</span>
<span class="k">break</span>
<span class="o">...</span>
</pre></div>
</div>
<p>This requires five lines and an extra variable,
<code class="docutils literal notranslate"><span class="pre">time_to_break_out_of_a</span></code>, to keep track of when to break out of the
outer (a) loop. And those five lines are spread across many lines of
code, making the control flow difficult to understand.</p>
<p>This technique is also error-prone. A programmer modifying this code
might inadvertently put new code after the end of the inner (b) loop
but before the test for <code class="docutils literal notranslate"><span class="pre">time_to_break_out_of_a</span></code>, instead of after
the test. This means that code which should have been skipped by
breaking out of the outer loop gets executed incorrectly.</p>
<p>This could also be written with an exception. The programmer would
declare a special exception, wrap the inner loop in a try, and catch
the exception and break when you see it:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">BreakOutOfALoop</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">a_list</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">b_list</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">if</span> <span class="n">condition_one</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
<span class="k">break</span>
<span class="o">...</span>
<span class="k">if</span> <span class="n">condition_two</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
<span class="k">raise</span> <span class="n">BreakOutOfALoop</span>
<span class="o">...</span>
<span class="k">except</span> <span class="n">BreakOutOfALoop</span><span class="p">:</span>
<span class="k">break</span>
<span class="o">...</span>
</pre></div>
</div>
<p>Again, though; this requires five lines and a new, single-purpose
exception class (instead of a new variable), and spreads basic control
flow out over many lines. And it breaks out of the inner loop with
<code class="docutils literal notranslate"><span class="pre">break</span></code> and out of the other loop with an exception, which is
inelegant. <a class="footnote-reference brackets" href="#toowtdi" id="id1">[1]</a></p>
<p>This next strategy might be the most elegant solution, assuming
condition_two() is inexpensive to compute:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">a_list</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">b_list</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">if</span> <span class="n">condition_one</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
<span class="k">break</span>
<span class="o">...</span>
<span class="k">if</span> <span class="n">condition_two</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
<span class="k">break</span>
<span class="o">...</span>
<span class="k">if</span> <span class="n">condition_two</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
<span class="k">break</span>
<span class="o">...</span>
</pre></div>
</div>
<p>Breaking twice is still inelegant. This implementation also relies on
the fact that the inner (b) loop bleeds b into the outer for loop,
which (although explicitly supported) is both surprising to novices,
and in my opinion counter-intuitive and poor practice.</p>
<p>The programmer must also still remember to put in both breaks on
condition two and not insert code before the second break. A single
conceptual action, breaking out of both loops on condition_two(),
requires four lines of code at two indentation levels, possibly
separated by many intervening lines at the end of the inner (b) loop.</p>
<section id="other-languages">
<h3><a class="toc-backref" href="#other-languages" role="doc-backlink">Other languages</a></h3>
<p>Now, put aside whatever dislike you may have for other programming
languages, and consider the syntax of labeled <code class="docutils literal notranslate"><span class="pre">break</span></code> and
<code class="docutils literal notranslate"><span class="pre">continue</span></code>. In Perl:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>ALOOP: foreach $a (@a_array){
...
BLOOP: foreach $b (@b_array){
...
if (condition_one($a,$b)){
last BLOOP; # same as plain old last;
}
...
if (condition_two($a,$b)){
last ALOOP;
}
...
}
...
}
</pre></div>
</div>
<p>(Notes: Perl uses <code class="docutils literal notranslate"><span class="pre">last</span></code> instead of <code class="docutils literal notranslate"><span class="pre">break</span></code>. The BLOOP labels
could be omitted; <code class="docutils literal notranslate"><span class="pre">last</span></code> and <code class="docutils literal notranslate"><span class="pre">continue</span></code> apply to the innermost
loop by default.)</p>
<p>PHP uses a number denoting the number of loops to break out of, rather
than a label:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>foreach ($a_array as $a){
....
foreach ($b_array as $b){
....
if (condition_one($a, $b)){
break 1; # same as plain old break
}
....
if (condition_two($a, $b)){
break 2;
}
....
}
...
}
</pre></div>
</div>
<p>C/C++, Java, and Ruby all have similar constructions.</p>
<p>The control flow regarding when to break out of the outer (a) loop is
fully encapsulated in the <code class="docutils literal notranslate"><span class="pre">break</span></code> statement which gets executed when
the break condition is satisfied. The depth of the break statement
does not matter. Control flow is not spread out. No extra variables,
exceptions, or re-checking or storing of control conditions is
required. There is no danger that code will get inadvertently
inserted after the end of the inner (b) loop and before the break
condition is re-checked inside the outer (a) loop. These are the
benefits that labeled <code class="docutils literal notranslate"><span class="pre">break</span></code> and <code class="docutils literal notranslate"><span class="pre">continue</span></code> would bring to
Python.</p>
</section>
</section>
<section id="what-this-pep-is-not">
<h2><a class="toc-backref" href="#what-this-pep-is-not" role="doc-backlink">What this PEP is not</a></h2>
<p>This PEP is not a proposal to add GOTO to Python. GOTO allows a
programmer to jump to an arbitrary block or line of code, and
generally makes control flow more difficult to follow. Although
<code class="docutils literal notranslate"><span class="pre">break</span></code> and <code class="docutils literal notranslate"><span class="pre">continue</span></code> (with or without support for labels) can be
considered a type of GOTO, it is much more restricted. Another Python
construct, <code class="docutils literal notranslate"><span class="pre">yield</span></code>, could also be considered a form of GOTO an
even less restrictive one. The goal of this PEP is to propose an
extension to the existing control flow tools <code class="docutils literal notranslate"><span class="pre">break</span></code> and
<code class="docutils literal notranslate"><span class="pre">continue</span></code>, to make control flow easier to understand, not more
difficult.</p>
<p>Labeled <code class="docutils literal notranslate"><span class="pre">break</span></code> and <code class="docutils literal notranslate"><span class="pre">continue</span></code> cannot transfer control to another
function or method. They cannot even transfer control to an arbitrary
line of code in the current scope. Currently, they can only affect
the behavior of a loop, and are quite different and much more
restricted than GOTO. This extension allows them to affect any
enclosing loop in the current name-space, but it does not change their
behavior to that of GOTO.</p>
</section>
<section id="specification">
<h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2>
<p>Under all of these proposals, <code class="docutils literal notranslate"><span class="pre">break</span></code> and <code class="docutils literal notranslate"><span class="pre">continue</span></code> by themselves
will continue to behave as they currently do, applying to the
innermost loop by default.</p>
<section id="proposal-a-explicit-labels">
<h3><a class="toc-backref" href="#proposal-a-explicit-labels" role="doc-backlink">Proposal A - Explicit labels</a></h3>
<p>The for and while loop syntax will be followed by an optional <code class="docutils literal notranslate"><span class="pre">as</span></code>
or <code class="docutils literal notranslate"><span class="pre">label</span></code> (contextual) keyword <a class="footnote-reference brackets" href="#keyword" id="id2">[2]</a> and then an identifier,
which may be used to identify the loop out of which to break (or which
should be continued).</p>
<p>The <code class="docutils literal notranslate"><span class="pre">break</span></code> (and <code class="docutils literal notranslate"><span class="pre">continue</span></code>) statements will be followed by an
optional identifier that refers to the loop out of which to break (or
which should be continued). Here is an example using the <code class="docutils literal notranslate"><span class="pre">as</span></code>
keyword:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">a_list</span> <span class="k">as</span> <span class="n">a_loop</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">b_list</span> <span class="k">as</span> <span class="n">b_loop</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">if</span> <span class="n">condition_one</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
<span class="k">break</span> <span class="n">b_loop</span> <span class="c1"># same as plain old break</span>
<span class="o">...</span>
<span class="k">if</span> <span class="n">condition_two</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
<span class="k">break</span> <span class="n">a_loop</span>
<span class="o">...</span>
<span class="o">...</span>
</pre></div>
</div>
<p>Or, with <code class="docutils literal notranslate"><span class="pre">label</span></code> instead of <code class="docutils literal notranslate"><span class="pre">as</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">a_list</span> <span class="n">label</span> <span class="n">a_loop</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">b_list</span> <span class="n">label</span> <span class="n">b_loop</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">if</span> <span class="n">condition_one</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
<span class="k">break</span> <span class="n">b_loop</span> <span class="c1"># same as plain old break</span>
<span class="o">...</span>
<span class="k">if</span> <span class="n">condition_two</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
<span class="k">break</span> <span class="n">a_loop</span>
<span class="o">...</span>
<span class="o">...</span>
</pre></div>
</div>
<p>This has all the benefits outlined above. It requires modifications
to the language syntax: the syntax of <code class="docutils literal notranslate"><span class="pre">break</span></code> and <code class="docutils literal notranslate"><span class="pre">continue</span></code>
syntax statements and for and while statements. It requires either a
new conditional keyword <code class="docutils literal notranslate"><span class="pre">label</span></code> or an extension to the conditional
keyword <code class="docutils literal notranslate"><span class="pre">as</span></code>. <a class="footnote-reference brackets" href="#as" id="id3">[3]</a> It is unlikely to require any changes to
existing Python programs. Passing an identifier not defined in the
local scope to <code class="docutils literal notranslate"><span class="pre">break</span></code> or <code class="docutils literal notranslate"><span class="pre">continue</span></code> would raise a NameError.</p>
</section>
<section id="proposal-b-numeric-break-continue">
<h3><a class="toc-backref" href="#proposal-b-numeric-break-continue" role="doc-backlink">Proposal B - Numeric break &amp; continue</a></h3>
<p>Rather than altering the syntax of <code class="docutils literal notranslate"><span class="pre">for</span></code> and <code class="docutils literal notranslate"><span class="pre">while</span></code> loops,
<code class="docutils literal notranslate"><span class="pre">break</span></code> and <code class="docutils literal notranslate"><span class="pre">continue</span></code> would take a numeric argument denoting the
enclosing loop which is being controlled, similar to PHP.</p>
<p>It seems more Pythonic to me for <code class="docutils literal notranslate"><span class="pre">break</span></code> and <code class="docutils literal notranslate"><span class="pre">continue</span></code> to refer
to loops indexing from zero, as opposed to indexing from one as PHP
does.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">a_list</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">b_list</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">if</span> <span class="n">condition_one</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">):</span>
<span class="k">break</span> <span class="mi">0</span> <span class="c1"># same as plain old break</span>
<span class="o">...</span>
<span class="k">if</span> <span class="n">condition_two</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">):</span>
<span class="k">break</span> <span class="mi">1</span>
<span class="o">...</span>
<span class="o">...</span>
</pre></div>
</div>
<p>Passing a number that was too large, or less than zero, or non-integer
to <code class="docutils literal notranslate"><span class="pre">break</span></code> or <code class="docutils literal notranslate"><span class="pre">continue</span></code> would (probably) raise an IndexError.</p>
<p>This proposal would not require any changes to existing Python
programs.</p>
</section>
<section id="proposal-c-the-reduplicative-method">
<h3><a class="toc-backref" href="#proposal-c-the-reduplicative-method" role="doc-backlink">Proposal C - The reduplicative method</a></h3>
<p>The syntax of <code class="docutils literal notranslate"><span class="pre">break</span></code> and <code class="docutils literal notranslate"><span class="pre">continue</span></code> would be altered to allow
multiple <code class="docutils literal notranslate"><span class="pre">break</span></code> and continue statements on the same line. Thus,
<code class="docutils literal notranslate"><span class="pre">break</span> <span class="pre">break</span></code> would break out of the first and second enclosing
loops.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">a_list</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">b_list</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">if</span> <span class="n">condition_one</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">):</span>
<span class="k">break</span> <span class="c1"># plain old break</span>
<span class="o">...</span>
<span class="k">if</span> <span class="n">condition_two</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">):</span>
<span class="k">break</span> <span class="k">break</span>
<span class="o">...</span>
<span class="o">...</span>
</pre></div>
</div>
<p>This would also allow the programmer to break out of the inner loop
and continue the next outermost simply by writing <code class="docutils literal notranslate"><span class="pre">break</span> <span class="pre">continue</span></code>,
<a class="footnote-reference brackets" href="#breakcontinue" id="id4">[4]</a> and so on. Im not sure what exception would be
raised if the programmer used more <code class="docutils literal notranslate"><span class="pre">break</span></code> or <code class="docutils literal notranslate"><span class="pre">continue</span></code>
statements than existing loops (perhaps a SyntaxError?).</p>
<p>I expect this proposal to get rejected because it will be judged too
difficult to understand.</p>
<p>This proposal would not require any changes to existing Python
programs.</p>
</section>
<section id="proposal-d-explicit-iterators">
<h3><a class="toc-backref" href="#proposal-d-explicit-iterators" role="doc-backlink">Proposal D - Explicit iterators</a></h3>
<p>Rather than embellishing for and while loop syntax with labels, the
programmer wishing to use labeled breaks would be required to create
the iterator explicitly and assign it to an identifier if he or she
wanted to <code class="docutils literal notranslate"><span class="pre">break</span></code> out of or <code class="docutils literal notranslate"><span class="pre">continue</span></code> that loop from within a
deeper loop.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a_iter</span> <span class="o">=</span> <span class="nb">iter</span><span class="p">(</span><span class="n">a_list</span><span class="p">)</span>
<span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">a_iter</span><span class="p">:</span>
<span class="o">...</span>
<span class="n">b_iter</span> <span class="o">=</span> <span class="nb">iter</span><span class="p">(</span><span class="n">b_list</span><span class="p">)</span>
<span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">b_iter</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">if</span> <span class="n">condition_one</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">):</span>
<span class="k">break</span> <span class="n">b_iter</span> <span class="c1"># same as plain old break</span>
<span class="o">...</span>
<span class="k">if</span> <span class="n">condition_two</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">):</span>
<span class="k">break</span> <span class="n">a_iter</span>
<span class="o">...</span>
<span class="o">...</span>
</pre></div>
</div>
<p>Passing a non-iterator object to <code class="docutils literal notranslate"><span class="pre">break</span></code> or <code class="docutils literal notranslate"><span class="pre">continue</span></code> would raise
a TypeError; and a nonexistent identifier would raise a NameError.
This proposal requires only one extra line to create a labeled loop,
and no extra lines to break out of a containing loop, and no changes
to existing Python programs.</p>
</section>
<section id="proposal-e-explicit-iterators-and-iterator-methods">
<h3><a class="toc-backref" href="#proposal-e-explicit-iterators-and-iterator-methods" role="doc-backlink">Proposal E - Explicit iterators and iterator methods</a></h3>
<p>This is a variant of Proposal D. Iterators would need be created
explicitly if anything other that the most basic use of <code class="docutils literal notranslate"><span class="pre">break</span></code> and
<code class="docutils literal notranslate"><span class="pre">continue</span></code> was required. Instead of modifying the syntax of
<code class="docutils literal notranslate"><span class="pre">break</span></code> and <code class="docutils literal notranslate"><span class="pre">continue</span></code>, <code class="docutils literal notranslate"><span class="pre">.break()</span></code> and <code class="docutils literal notranslate"><span class="pre">.continue()</span></code> methods
could be added to the Iterator type.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a_iter</span> <span class="o">=</span> <span class="nb">iter</span><span class="p">(</span><span class="n">a_list</span><span class="p">)</span>
<span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">a_iter</span><span class="p">:</span>
<span class="o">...</span>
<span class="n">b_iter</span> <span class="o">=</span> <span class="nb">iter</span><span class="p">(</span><span class="n">b_list</span><span class="p">)</span>
<span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">b_iter</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">if</span> <span class="n">condition_one</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">):</span>
<span class="n">b_iter</span><span class="o">.</span><span class="k">break</span><span class="p">()</span> <span class="c1"># same as plain old break</span>
<span class="o">...</span>
<span class="k">if</span> <span class="n">condition_two</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">):</span>
<span class="n">a_iter</span><span class="o">.</span><span class="k">break</span><span class="p">()</span>
<span class="o">...</span>
<span class="o">...</span>
</pre></div>
</div>
<p>I expect that this proposal will get rejected on the grounds of sheer
ugliness. However, it requires no changes to the language syntax
whatsoever, nor does it require any changes to existing Python
programs.</p>
</section>
</section>
<section id="implementation">
<h2><a class="toc-backref" href="#implementation" role="doc-backlink">Implementation</a></h2>
<p>I have never looked at the Python language implementation itself, so I
have no idea how difficult this would be to implement. If this PEP is
accepted, but no one is available to write the feature, I will try to
implement it myself.</p>
</section>
<section id="footnotes">
<h2><a class="toc-backref" href="#footnotes" role="doc-backlink">Footnotes</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="toowtdi" role="doc-footnote">
<dt class="label" id="toowtdi">[<a href="#id1">1</a>]</dt>
<dd>Breaking some loops with exceptions is inelegant because
its a violation of Theres Only One Way To Do It.</aside>
<aside class="footnote brackets" id="keyword" role="doc-footnote">
<dt class="label" id="keyword">[<a href="#id2">2</a>]</dt>
<dd>Or really any new contextual keyword that the community
likes: <code class="docutils literal notranslate"><span class="pre">as</span></code>, <code class="docutils literal notranslate"><span class="pre">label</span></code>, <code class="docutils literal notranslate"><span class="pre">labeled</span></code>, <code class="docutils literal notranslate"><span class="pre">loop</span></code>, <code class="docutils literal notranslate"><span class="pre">name</span></code>, <code class="docutils literal notranslate"><span class="pre">named</span></code>,
<code class="docutils literal notranslate"><span class="pre">walrus</span></code>, whatever.</aside>
<aside class="footnote brackets" id="as" role="doc-footnote">
<dt class="label" id="as">[<a href="#id3">3</a>]</dt>
<dd>The use of <code class="docutils literal notranslate"><span class="pre">as</span></code> in a similar context has been proposed here,
<a class="reference external" href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1714448&amp;group_id=5470&amp;atid=355470">http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1714448&amp;group_id=5470&amp;atid=355470</a>
but to my knowledge this idea has not been written up as a PEP.</aside>
<aside class="footnote brackets" id="breakcontinue" role="doc-footnote">
<dt class="label" id="breakcontinue">[<a href="#id4">4</a>]</dt>
<dd>To continue the Nth outer loop, you would write
break N-1 times and then continue. Only one <code class="docutils literal notranslate"><span class="pre">continue</span></code> would be
allowed, and only at the end of a sequence of breaks. <code class="docutils literal notranslate"><span class="pre">continue</span>
<span class="pre">break</span></code> or <code class="docutils literal notranslate"><span class="pre">continue</span> <span class="pre">continue</span></code> makes no sense.</aside>
</aside>
</section>
<section id="resources">
<h2><a class="toc-backref" href="#resources" role="doc-backlink">Resources</a></h2>
<p>This issue has come up before, although it has never been resolved, to
my knowledge.</p>
<ul class="simple">
<li><a class="reference external" href="http://groups.google.com/group/comp.lang.python/browse_thread/thread/6da848f762c9cf58/979ca3cd42633b52?lnk=gst&amp;q=labeled+break&amp;rnum=3#979ca3cd42633b52">labeled breaks</a>, on comp.lang.python, in the context of
<code class="docutils literal notranslate"><span class="pre">do...while</span></code> loops</li>
<li><a class="reference external" href="https://mail.python.org/pipermail/python-list/1999-September/#11080">break LABEL vs. exceptions + PROPOSAL</a>, on python-list, as
compared to using Exceptions for flow control</li>
<li><a class="reference external" href="https://mail.python.org/pipermail/python-list/2001-April/#78439">Named code blocks</a> on python-list, a suggestion motivated by the
desire for labeled break / continue</li>
<li><a class="reference external" href="http://mail-archives.apache.org/mod_mbox/httpd-python-cvs/200511.mbox/%3C20051112204322.4010.qmail&#64;minotaur.apache.org%3E">mod_python bug fix</a> An example of someone setting a flag inside
an inner loop that triggers a continue in the containing loop, to
work around the absence of labeled break and continue</li>
</ul>
</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>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-3136.rst">https://github.com/python/peps/blob/main/peps/pep-3136.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-3136.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="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a><ul>
<li><a class="reference internal" href="#other-languages">Other languages</a></li>
</ul>
</li>
<li><a class="reference internal" href="#what-this-pep-is-not">What this PEP is not</a></li>
<li><a class="reference internal" href="#specification">Specification</a><ul>
<li><a class="reference internal" href="#proposal-a-explicit-labels">Proposal A - Explicit labels</a></li>
<li><a class="reference internal" href="#proposal-b-numeric-break-continue">Proposal B - Numeric break &amp; continue</a></li>
<li><a class="reference internal" href="#proposal-c-the-reduplicative-method">Proposal C - The reduplicative method</a></li>
<li><a class="reference internal" href="#proposal-d-explicit-iterators">Proposal D - Explicit iterators</a></li>
<li><a class="reference internal" href="#proposal-e-explicit-iterators-and-iterator-methods">Proposal E - Explicit iterators and iterator methods</a></li>
</ul>
</li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#footnotes">Footnotes</a></li>
<li><a class="reference internal" href="#resources">Resources</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-3136.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>