python-peps/pep-0308/index.html

557 lines
41 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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 308 Conditional Expressions | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0308/">
<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 308 Conditional Expressions | peps.python.org'>
<meta property="og:description" content="Python Enhancement Proposals (PEPs)">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0308/">
<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 308</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 308 Conditional Expressions</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Guido van Rossum, Raymond Hettinger</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</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">07-Feb-2003</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.5</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even">07-Feb-2003, 11-Feb-2003</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#adding-a-conditional-expression">Adding a conditional expression</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#introduction-to-earlier-draft-of-the-pep-kept-for-historical-purposes">Introduction to earlier draft of the PEP (kept for historical purposes)</a></li>
<li><a class="reference internal" href="#proposal">Proposal</a></li>
<li><a class="reference internal" href="#alternatives">Alternatives</a></li>
<li><a class="reference internal" href="#summary-of-the-current-state-of-the-discussion">Summary of the Current State of the Discussion</a></li>
<li><a class="reference internal" href="#short-circuit-behavior">Short-Circuit Behavior</a></li>
<li><a class="reference internal" href="#detailed-results-of-voting">Detailed Results of Voting</a><ul>
<li><a class="reference internal" href="#choice-key">CHOICE KEY</a></li>
<li><a class="reference internal" href="#detail-for-write-in-votes-and-their-ranking">Detail for write-in votes and their ranking</a></li>
</ul>
</li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="adding-a-conditional-expression">
<h2><a class="toc-backref" href="#adding-a-conditional-expression" role="doc-backlink">Adding a conditional expression</a></h2>
<p>On 9/29/2005, Guido decided to add conditional expressions in the
form of “X if C else Y”. <a class="footnote-reference brackets" href="#id4" id="id1">[1]</a></p>
<p>The motivating use case was the prevalence of error-prone attempts
to achieve the same effect using “and” and “or”. <a class="footnote-reference brackets" href="#id5" id="id2">[2]</a></p>
<p>Previous community efforts to add a conditional expression were
stymied by a lack of consensus on the best syntax. That issue was
resolved by simply deferring to a BDFL best judgment call.</p>
<p>The decision was validated by reviewing how the syntax fared when
applied throughout the standard library (this review approximates a
sampling of real-world use cases, across a variety of applications,
written by a number of programmers with diverse backgrounds). <a class="footnote-reference brackets" href="#id6" id="id3">[3]</a></p>
<p>The following change will be made to the grammar. (The or_test
symbols is new, the others are modified.)</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">test</span><span class="p">:</span> <span class="n">or_test</span> <span class="p">[</span><span class="s1">&#39;if&#39;</span> <span class="n">or_test</span> <span class="s1">&#39;else&#39;</span> <span class="n">test</span><span class="p">]</span> <span class="o">|</span> <span class="n">lambdef</span>
<span class="n">or_test</span><span class="p">:</span> <span class="n">and_test</span> <span class="p">(</span><span class="s1">&#39;or&#39;</span> <span class="n">and_test</span><span class="p">)</span><span class="o">*</span>
<span class="o">...</span>
<span class="n">testlist_safe</span><span class="p">:</span> <span class="n">or_test</span> <span class="p">[(</span><span class="s1">&#39;,&#39;</span> <span class="n">or_test</span><span class="p">)</span><span class="o">+</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span><span class="p">]]</span>
<span class="o">...</span>
<span class="n">gen_for</span><span class="p">:</span> <span class="s1">&#39;for&#39;</span> <span class="n">exprlist</span> <span class="s1">&#39;in&#39;</span> <span class="n">or_test</span> <span class="p">[</span><span class="n">gen_iter</span><span class="p">]</span>
</pre></div>
</div>
<p>The new syntax nearly introduced a minor syntactical backwards
incompatibility. In previous Python versions, the following is
legal:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">f</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="p">,</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="o">**</span><span class="mi">2</span> <span class="k">if</span> <span class="n">f</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">]</span>
</pre></div>
</div>
<p>(I.e. a list comprehension where the sequence following in is an
unparenthesized series of lambdas or just one lambda, even.)</p>
<p>In Python 3.0, the series of lambdas will have to be
parenthesized, e.g.:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">f</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="p">,</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="o">**</span><span class="mi">2</span><span class="p">)</span> <span class="k">if</span> <span class="n">f</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">]</span>
</pre></div>
</div>
<p>This is because lambda binds less tight than the if-else
expression, but in this context, the lambda could already be
followed by an if keyword that binds less tightly still (for
details, consider the grammar changes shown above).</p>
<p>However, in Python 2.5, a slightly different grammar is used that
is more backwards compatible, but constrains the grammar of a
lambda used in this position by forbidding the lambdas body to
contain an unparenthesized condition expression. Examples:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">f</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span> <span class="k">if</span> <span class="n">x</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="k">else</span> <span class="o">-</span><span class="mi">1</span><span class="p">)]</span> <span class="c1"># OK</span>
<span class="p">[</span><span class="n">f</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="mi">1</span><span class="p">,</span> <span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span> <span class="k">if</span> <span class="n">x</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="k">else</span> <span class="o">-</span><span class="mi">1</span><span class="p">)]</span> <span class="c1"># OK</span>
<span class="p">[</span><span class="n">f</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="mi">1</span><span class="p">,</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="p">(</span><span class="n">x</span> <span class="k">if</span> <span class="n">x</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="k">else</span> <span class="o">-</span><span class="mi">1</span><span class="p">)]</span> <span class="c1"># OK</span>
<span class="p">[</span><span class="n">f</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="mi">1</span><span class="p">,</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span> <span class="k">if</span> <span class="n">x</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="k">else</span> <span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="c1"># INVALID</span>
</pre></div>
</div>
</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="id4" role="doc-footnote">
<dt class="label" id="id4">[<a href="#id1">1</a>]</dt>
<dd>Pronouncement
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2005-September/056846.html">https://mail.python.org/pipermail/python-dev/2005-September/056846.html</a></aside>
<aside class="footnote brackets" id="id5" role="doc-footnote">
<dt class="label" id="id5">[<a href="#id2">2</a>]</dt>
<dd>Motivating use case:
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2005-September/056546.html">https://mail.python.org/pipermail/python-dev/2005-September/056546.html</a>
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2005-September/056510.html">https://mail.python.org/pipermail/python-dev/2005-September/056510.html</a></aside>
<aside class="footnote brackets" id="id6" role="doc-footnote">
<dt class="label" id="id6">[<a href="#id3">3</a>]</dt>
<dd>Review in the context of real-world code fragments:
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2005-September/056803.html">https://mail.python.org/pipermail/python-dev/2005-September/056803.html</a></aside>
</aside>
</section>
<section id="introduction-to-earlier-draft-of-the-pep-kept-for-historical-purposes">
<h2><a class="toc-backref" href="#introduction-to-earlier-draft-of-the-pep-kept-for-historical-purposes" role="doc-backlink">Introduction to earlier draft of the PEP (kept for historical purposes)</a></h2>
<p>Requests for an if-then-else (“ternary”) expression keep coming up
on comp.lang.python. This PEP contains a concrete proposal of a
fairly Pythonic syntax. This is the communitys one chance: if
this PEP is approved with a clear majority, it will be implemented
in Python 2.4. If not, the PEP will be augmented with a summary
of the reasons for rejection and the subject better not come up
again. While the BDFL is co-author of this PEP, he is neither in
favor nor against this proposal; it is up to the community to
decide. If the community cant decide, the BDFL will reject the
PEP.</p>
<p>After unprecedented community response (very good arguments were
made both pro and con) this PEP has been revised with the help of
Raymond Hettinger. Without going through a complete revision
history, the main changes are a different proposed syntax, an
overview of proposed alternatives, the state of the current
discussion, and a discussion of short-circuit behavior.</p>
<p>Following the discussion, a vote was held. While there was an overall
interest in having some form of if-then-else expressions, no one
format was able to draw majority support. Accordingly, the PEP was
rejected due to the lack of an overwhelming majority for change.
Also, a Python design principle has been to prefer the status quo
whenever there are doubts about which path to take.</p>
</section>
<section id="proposal">
<h2><a class="toc-backref" href="#proposal" role="doc-backlink">Proposal</a></h2>
<p>The proposed syntax is as follows:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="k">if</span> <span class="o">&lt;</span><span class="n">condition</span><span class="o">&gt;</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">expression1</span><span class="o">&gt;</span> <span class="k">else</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">expression2</span><span class="o">&gt;</span><span class="p">)</span>
</pre></div>
</div>
<p>Note that the enclosing parentheses are not optional.</p>
<p>The resulting expression is evaluated like this:</p>
<ul class="simple">
<li>First, &lt;condition&gt; is evaluated.</li>
<li>If &lt;condition&gt; is true, &lt;expression1&gt; is evaluated and is the
result of the whole thing.</li>
<li>If &lt;condition&gt; is false, &lt;expression2&gt; is evaluated and is the
result of the whole thing.</li>
</ul>
<p>A natural extension of this syntax is to allow one or more elif
parts:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="k">if</span> <span class="o">&lt;</span><span class="n">cond1</span><span class="o">&gt;</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">expr1</span><span class="o">&gt;</span> <span class="k">elif</span> <span class="o">&lt;</span><span class="n">cond2</span><span class="o">&gt;</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">expr2</span><span class="o">&gt;</span> <span class="o">...</span> <span class="k">else</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">exprN</span><span class="o">&gt;</span><span class="p">)</span>
</pre></div>
</div>
<p>This will be implemented if the proposal is accepted.</p>
<p>The downsides to the proposal are:</p>
<ul class="simple">
<li>the required parentheses</li>
<li>confusability with statement syntax</li>
<li>additional semantic loading of colons</li>
</ul>
<p>Note that at most one of &lt;expression1&gt; and &lt;expression2&gt; is
evaluated. This is called a “short-circuit expression”; it is
similar to the way the second operand of and / or is only
evaluated if the first operand is true / false.</p>
<p>A common way to emulate an if-then-else expression is:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&lt;</span><span class="n">condition</span><span class="o">&gt;</span> <span class="ow">and</span> <span class="o">&lt;</span><span class="n">expression1</span><span class="o">&gt;</span> <span class="ow">or</span> <span class="o">&lt;</span><span class="n">expression2</span><span class="o">&gt;</span>
</pre></div>
</div>
<p>However, this doesnt work the same way: it returns &lt;expression2&gt;
when &lt;expression1&gt; is false! See FAQ 4.16 for alternatives that
work however, they are pretty ugly and require much more effort
to understand.</p>
</section>
<section id="alternatives">
<h2><a class="toc-backref" href="#alternatives" role="doc-backlink">Alternatives</a></h2>
<p>Holger Krekel proposed a new, minimally invasive variant:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&lt;</span><span class="n">condition</span><span class="o">&gt;</span> <span class="ow">and</span> <span class="o">&lt;</span><span class="n">expression1</span><span class="o">&gt;</span> <span class="k">else</span> <span class="o">&lt;</span><span class="n">expression2</span><span class="o">&gt;</span>
</pre></div>
</div>
<p>The concept behind it is that a nearly complete ternary operator
already exists with and/or and this proposal is the least invasive
change that makes it complete. Many respondants on the
newsgroup found this to be the most pleasing alternative.
However, a couple of respondants were able to post examples
that were mentally difficult to parse. Later it was pointed
out that this construct works by having the “else” change the
existing meaning of “and”.</p>
<p>As a result, there is increasing support for Christian Tismers
proposed variant of the same idea:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&lt;</span><span class="n">condition</span><span class="o">&gt;</span> <span class="n">then</span> <span class="o">&lt;</span><span class="n">expression1</span><span class="o">&gt;</span> <span class="k">else</span> <span class="o">&lt;</span><span class="n">expression2</span><span class="o">&gt;</span>
</pre></div>
</div>
<p>The advantages are simple visual parsing, no required parentheses,
no change in the semantics of existing keywords, not as likely
as the proposal to be confused with statement syntax, and does
not further overload the colon. The disadvantage is the
implementation costs of introducing a new keyword. However,
unlike other new keywords, the word “then” seems unlikely to
have been used as a name in existing programs.</p>
<p></p>
<p>Many C-derived languages use this syntax:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&lt;condition&gt; ? &lt;expression1&gt; : &lt;expression2&gt;
</pre></div>
</div>
<p>Eric Raymond even implemented this. The BDFL rejected this for
several reasons: the colon already has many uses in Python (even
though it would actually not be ambiguous, because the question
mark requires a matching colon); for people not used to C-derived
language, it is hard to understand.</p>
<p></p>
<p>The original version of this PEP proposed the following syntax:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&lt;</span><span class="n">expression1</span><span class="o">&gt;</span> <span class="k">if</span> <span class="o">&lt;</span><span class="n">condition</span><span class="o">&gt;</span> <span class="k">else</span> <span class="o">&lt;</span><span class="n">expression2</span><span class="o">&gt;</span>
</pre></div>
</div>
<p>The out-of-order arrangement was found to be too uncomfortable
for many of participants in the discussion; especially when
&lt;expression1&gt; is long, its easy to miss the conditional while
skimming.</p>
<p></p>
<p>Some have suggested adding a new builtin instead of extending the
syntax of the language. For example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">cond</span><span class="p">(</span><span class="o">&lt;</span><span class="n">condition</span><span class="o">&gt;</span><span class="p">,</span> <span class="o">&lt;</span><span class="n">expression1</span><span class="o">&gt;</span><span class="p">,</span> <span class="o">&lt;</span><span class="n">expression2</span><span class="o">&gt;</span><span class="p">)</span>
</pre></div>
</div>
<p>This wont work the way a syntax extension will because both
expression1 and expression2 must be evaluated before the function
is called. Theres no way to short-circuit the expression
evaluation. It could work if cond (or some other name) were
made a keyword, but that has all the disadvantages of adding a new
keyword, plus confusing syntax: it <strong>looks</strong> like a function call so
a casual reader might expect both &lt;expression1&gt; and &lt;expression2&gt;
to be evaluated.</p>
</section>
<section id="summary-of-the-current-state-of-the-discussion">
<h2><a class="toc-backref" href="#summary-of-the-current-state-of-the-discussion" role="doc-backlink">Summary of the Current State of the Discussion</a></h2>
<p>Groups are falling into one of three camps:</p>
<ol class="arabic">
<li>Adopt a ternary operator built using punctuation characters:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&lt;condition&gt; ? &lt;expression1&gt; : &lt;expression2&gt;
</pre></div>
</div>
</li>
<li>Adopt a ternary operator built using new or existing keywords.
The leading examples are:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&lt;</span><span class="n">condition</span><span class="o">&gt;</span> <span class="n">then</span> <span class="o">&lt;</span><span class="n">expression1</span><span class="o">&gt;</span> <span class="k">else</span> <span class="o">&lt;</span><span class="n">expression2</span><span class="o">&gt;</span>
<span class="p">(</span><span class="k">if</span> <span class="o">&lt;</span><span class="n">condition</span><span class="o">&gt;</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">expression1</span><span class="o">&gt;</span> <span class="k">else</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">expression2</span><span class="o">&gt;</span><span class="p">)</span>
</pre></div>
</div>
</li>
<li>Do nothing.</li>
</ol>
<p>The first two positions are relatively similar.</p>
<p>Some find that any form of punctuation makes the language more
cryptic. Others find that punctuation style is appropriate for
expressions rather than statements and helps avoid a COBOL style:
3 plus 4 times 5.</p>
<p>Adapting existing keywords attempts to improve on punctuation
through explicit meaning and a more tidy appearance. The downside
is some loss of the economy-of-expression provided by punctuation
operators. The other downside is that it creates some degree of
confusion between the two meanings and two usages of the keywords.</p>
<p>Those difficulties are overcome by options which introduce new
keywords which take more effort to implement.</p>
<p>The last position is doing nothing. Arguments in favor include
keeping the language simple and concise; maintaining backwards
compatibility; and that any every use case can already be already
expressed in terms of “if” and “else”. Lambda expressions are an
exception as they require the conditional to be factored out into
a separate function definition.</p>
<p>The arguments against doing nothing are that the other choices
allow greater economy of expression and that current practices
show a propensity for erroneous uses of “and”, “or”, or one their
more complex, less visually unappealing workarounds.</p>
</section>
<section id="short-circuit-behavior">
<h2><a class="toc-backref" href="#short-circuit-behavior" role="doc-backlink">Short-Circuit Behavior</a></h2>
<p>The principal difference between the ternary operator and the
<code class="docutils literal notranslate"><span class="pre">cond()</span></code> function is that the latter provides an expression form but
does not provide short-circuit evaluation.</p>
<p>Short-circuit evaluation is desirable on three occasions:</p>
<ol class="arabic simple">
<li>When an expression has side-effects</li>
<li>When one or both of the expressions are resource intensive</li>
<li>When the condition serves as a guard for the validity of the
expression.</li>
</ol>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span># Example where all three reasons apply
data = isinstance(source, file) ? source.readlines()
: source.split()
</pre></div>
</div>
<ol class="arabic simple">
<li><code class="docutils literal notranslate"><span class="pre">readlines()</span></code> moves the file pointer</li>
<li>for long sources, both alternatives take time</li>
<li><code class="docutils literal notranslate"><span class="pre">split()</span></code> is only valid for strings and <code class="docutils literal notranslate"><span class="pre">readlines()</span></code> is only
valid for file objects.</li>
</ol>
<p>Supporters of a <code class="docutils literal notranslate"><span class="pre">cond()</span></code> function point out that the need for
short-circuit evaluation is rare. Scanning through existing code
directories, they found that if/else did not occur often; and of
those only a few contained expressions that could be helped by
<code class="docutils literal notranslate"><span class="pre">cond()</span></code> or a ternary operator; and that most of those had no need
for short-circuit evaluation. Hence, <code class="docutils literal notranslate"><span class="pre">cond()</span></code> would suffice for
most needs and would spare efforts to alter the syntax of the
language.</p>
<p>More supporting evidence comes from scans of C code bases which
show that its ternary operator used very rarely (as a percentage
of lines of code).</p>
<p>A counterpoint to that analysis is that the availability of a
ternary operator helped the programmer in every case because it
spared the need to search for side-effects. Further, it would
preclude errors arising from distant modifications which introduce
side-effects. The latter case has become more of a reality with
the advent of properties where even attribute access can be given
side-effects.</p>
<p>The BDFLs position is that short-circuit behavior is essential
for an if-then-else construct to be added to the language.</p>
</section>
<section id="detailed-results-of-voting">
<h2><a class="toc-backref" href="#detailed-results-of-voting" role="doc-backlink">Detailed Results of Voting</a></h2>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Votes</span> <span class="n">rejecting</span> <span class="nb">all</span> <span class="n">options</span><span class="p">:</span> <span class="mi">82</span>
<span class="n">Votes</span> <span class="k">with</span> <span class="n">rank</span> <span class="n">ordering</span><span class="p">:</span> <span class="mi">436</span>
<span class="o">---</span>
<span class="n">Total</span> <span class="n">votes</span> <span class="n">received</span><span class="p">:</span> <span class="mi">518</span>
<span class="n">ACCEPT</span> <span class="n">REJECT</span> <span class="n">TOTAL</span>
<span class="o">---------------------</span> <span class="o">---------------------</span> <span class="o">-----</span>
<span class="n">Rank1</span> <span class="n">Rank2</span> <span class="n">Rank3</span> <span class="n">Rank1</span> <span class="n">Rank2</span> <span class="n">Rank3</span>
<span class="n">Letter</span>
<span class="n">A</span> <span class="mi">51</span> <span class="mi">33</span> <span class="mi">19</span> <span class="mi">18</span> <span class="mi">20</span> <span class="mi">20</span> <span class="mi">161</span>
<span class="n">B</span> <span class="mi">45</span> <span class="mi">46</span> <span class="mi">21</span> <span class="mi">9</span> <span class="mi">24</span> <span class="mi">23</span> <span class="mi">168</span>
<span class="n">C</span> <span class="mi">94</span> <span class="mi">54</span> <span class="mi">29</span> <span class="mi">20</span> <span class="mi">20</span> <span class="mi">18</span> <span class="mi">235</span>
<span class="n">D</span> <span class="mi">71</span> <span class="mi">40</span> <span class="mi">31</span> <span class="mi">5</span> <span class="mi">28</span> <span class="mi">31</span> <span class="mi">206</span>
<span class="n">E</span> <span class="mi">7</span> <span class="mi">7</span> <span class="mi">10</span> <span class="mi">3</span> <span class="mi">5</span> <span class="mi">32</span>
<span class="n">F</span> <span class="mi">14</span> <span class="mi">19</span> <span class="mi">10</span> <span class="mi">7</span> <span class="mi">17</span> <span class="mi">67</span>
<span class="n">G</span> <span class="mi">7</span> <span class="mi">6</span> <span class="mi">10</span> <span class="mi">1</span> <span class="mi">2</span> <span class="mi">4</span> <span class="mi">30</span>
<span class="n">H</span> <span class="mi">20</span> <span class="mi">22</span> <span class="mi">17</span> <span class="mi">4</span> <span class="mi">10</span> <span class="mi">25</span> <span class="mi">98</span>
<span class="n">I</span> <span class="mi">16</span> <span class="mi">20</span> <span class="mi">9</span> <span class="mi">5</span> <span class="mi">5</span> <span class="mi">20</span> <span class="mi">75</span>
<span class="n">J</span> <span class="mi">6</span> <span class="mi">17</span> <span class="mi">5</span> <span class="mi">1</span> <span class="mi">10</span> <span class="mi">39</span>
<span class="n">K</span> <span class="mi">1</span> <span class="mi">6</span> <span class="mi">4</span> <span class="mi">13</span> <span class="mi">24</span>
<span class="n">L</span> <span class="mi">1</span> <span class="mi">2</span> <span class="mi">3</span> <span class="mi">3</span> <span class="mi">9</span>
<span class="n">M</span> <span class="mi">7</span> <span class="mi">3</span> <span class="mi">4</span> <span class="mi">2</span> <span class="mi">5</span> <span class="mi">11</span> <span class="mi">32</span>
<span class="n">N</span> <span class="mi">2</span> <span class="mi">3</span> <span class="mi">4</span> <span class="mi">2</span> <span class="mi">11</span>
<span class="n">O</span> <span class="mi">1</span> <span class="mi">6</span> <span class="mi">5</span> <span class="mi">1</span> <span class="mi">4</span> <span class="mi">9</span> <span class="mi">26</span>
<span class="n">P</span> <span class="mi">5</span> <span class="mi">3</span> <span class="mi">6</span> <span class="mi">1</span> <span class="mi">5</span> <span class="mi">7</span> <span class="mi">27</span>
<span class="n">Q</span> <span class="mi">18</span> <span class="mi">7</span> <span class="mi">15</span> <span class="mi">6</span> <span class="mi">5</span> <span class="mi">11</span> <span class="mi">62</span>
<span class="n">Z</span> <span class="mi">1</span> <span class="mi">1</span>
<span class="o">---</span> <span class="o">---</span> <span class="o">---</span> <span class="o">---</span> <span class="o">---</span> <span class="o">---</span> <span class="o">----</span>
<span class="n">Total</span> <span class="mi">363</span> <span class="mi">286</span> <span class="mi">202</span> <span class="mi">73</span> <span class="mi">149</span> <span class="mi">230</span> <span class="mi">1303</span>
<span class="n">RejectAll</span> <span class="mi">82</span> <span class="mi">82</span> <span class="mi">82</span> <span class="mi">246</span>
<span class="o">---</span> <span class="o">---</span> <span class="o">---</span> <span class="o">---</span> <span class="o">---</span> <span class="o">---</span> <span class="o">----</span>
<span class="n">Total</span> <span class="mi">363</span> <span class="mi">286</span> <span class="mi">202</span> <span class="mi">155</span> <span class="mi">231</span> <span class="mi">312</span> <span class="mi">1549</span>
</pre></div>
</div>
<section id="choice-key">
<h3><a class="toc-backref" href="#choice-key" role="doc-backlink">CHOICE KEY</a></h3>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>A. x if C else y
B. if C then x else y
C. (if C: x else: y)
D. C ? x : y
E. C ? x ! y
F. cond(C, x, y)
G. C ?? x || y
H. C then x else y
I. x when C else y
J. C ? x else y
K. C -&gt; x else y
L. C -&gt; (x, y)
M. [x if C else y]
N. ifelse C: x else y
O. &lt;if C then x else y&gt;
P. C and x else y
Q. any write-in vote
</pre></div>
</div>
</section>
<section id="detail-for-write-in-votes-and-their-ranking">
<h3><a class="toc-backref" href="#detail-for-write-in-votes-and-their-ranking" role="doc-backlink">Detail for write-in votes and their ranking</a></h3>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>3: Q reject y x C elsethenif
2: Q accept (C ? x ! y)
3: Q reject ...
3: Q accept ? C : x : y
3: Q accept (x if C, y otherwise)
3: Q reject ...
3: Q reject NONE
1: Q accept select : (&lt;c1&gt; : &lt;val1&gt;; [&lt;cx&gt; : &lt;valx&gt;; ]* elseval)
2: Q reject if C: t else: f
3: Q accept C selects x else y
2: Q accept iff(C, x, y) # &quot;if-function&quot;
1: Q accept (y, x)[C]
1: Q accept C true: x false: y
3: Q accept C then: x else: y
3: Q reject
3: Q accept (if C: x elif C2: y else: z)
3: Q accept C -&gt; x : y
1: Q accept x (if C), y
1: Q accept if c: x else: y
3: Q accept (c).{True:1, False:2}
2: Q accept if c: x else: y
3: Q accept (c).{True:1, False:2}
3: Q accept if C: x else y
1: Q accept (x if C else y)
1: Q accept ifelse(C, x, y)
2: Q reject x or y &lt;- C
1: Q accept (C ? x : y) required parens
1: Q accept iif(C, x, y)
1: Q accept ?(C, x, y)
1: Q accept switch-case
2: Q accept multi-line if/else
1: Q accept C: x else: y
2: Q accept (C): x else: y
3: Q accept if C: x else: y
1: Q accept x if C, else y
1: Q reject choice: c1-&gt;a; c2-&gt;b; ...; z
3: Q accept [if C then x else y]
3: Q reject no other choice has x as the first element
1: Q accept (x,y) ? C
3: Q accept x if C else y (The &quot;else y&quot; being optional)
1: Q accept (C ? x , y)
1: Q accept any outcome (i.e form or plain rejection) from a usability study
1: Q reject (x if C else y)
1: Q accept (x if C else y)
2: Q reject NONE
3: Q reject NONE
3: Q accept (C ? x else y)
3: Q accept x when C else y
2: Q accept (x if C else y)
2: Q accept cond(C1, x1, C2, x2, C3, x3,...)
1: Q accept (if C1: x elif C2: y else: z)
1: Q reject cond(C, :x, :y)
3: Q accept (C and [x] or [y])[0]
2: Q reject
3: Q reject
3: Q reject all else
1: Q reject no-change
3: Q reject deliberately omitted as I have no interest in any other proposal
2: Q reject (C then x else Y)
1: Q accept if C: x else: y
1: Q reject (if C then x else y)
3: Q reject C?(x, y)
</pre></div>
</div>
</section>
</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-0308.rst">https://github.com/python/peps/blob/main/peps/pep-0308.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0308.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="#adding-a-conditional-expression">Adding a conditional expression</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#introduction-to-earlier-draft-of-the-pep-kept-for-historical-purposes">Introduction to earlier draft of the PEP (kept for historical purposes)</a></li>
<li><a class="reference internal" href="#proposal">Proposal</a></li>
<li><a class="reference internal" href="#alternatives">Alternatives</a></li>
<li><a class="reference internal" href="#summary-of-the-current-state-of-the-discussion">Summary of the Current State of the Discussion</a></li>
<li><a class="reference internal" href="#short-circuit-behavior">Short-Circuit Behavior</a></li>
<li><a class="reference internal" href="#detailed-results-of-voting">Detailed Results of Voting</a><ul>
<li><a class="reference internal" href="#choice-key">CHOICE KEY</a></li>
<li><a class="reference internal" href="#detail-for-write-in-votes-and-their-ranking">Detail for write-in votes and their ranking</a></li>
</ul>
</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-0308.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>