python-peps/pep-0379/index.html

301 lines
24 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 379 Adding an Assignment Expression | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0379/">
<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 379 Adding an Assignment Expression | peps.python.org'>
<meta property="og:description" content="This PEP adds a new assignment expression to the Python language to make it possible to assign the result of an expression in almost any place. The new expression will allow the assignment of the result of an expression at first use (in a comparison fo...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0379/">
<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 adds a new assignment expression to the Python language to make it possible to assign the result of an expression in almost any place. The new expression will allow the assignment of the result of an expression at first use (in a comparison fo...">
<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 379</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 379 Adding an Assignment Expression</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Jervis Whitley &lt;jervisau&#32;&#97;t&#32;gmail.com&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Removed from consideration by sponsor or authors">Withdrawn</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">14-Mar-2009</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.7, 3.2</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="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#motivation-and-summary">Motivation and Summary</a></li>
<li><a class="reference internal" href="#use-cases">Use Cases</a></li>
<li><a class="reference internal" href="#specification">Specification</a></li>
<li><a class="reference internal" href="#examples-from-the-standard-library">Examples from the Standard Library</a></li>
<li><a class="reference internal" href="#examples">Examples</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>This PEP adds a new assignment expression to the Python language
to make it possible to assign the result of an expression in
almost any place. The new expression will allow the assignment of
the result of an expression at first use (in a comparison for
example).</p>
</section>
<section id="motivation-and-summary">
<h2><a class="toc-backref" href="#motivation-and-summary" role="doc-backlink">Motivation and Summary</a></h2>
<p>Issue1714448 “if something as x:” <a class="footnote-reference brackets" href="#id2" id="id1">[1]</a> describes a feature to allow
assignment of the result of an expression in an if statement to a
name. It supposed that the <code class="docutils literal notranslate"><span class="pre">as</span></code> syntax could be borrowed for this
purpose. Many times it is not the expression itself that is
interesting, rather one of the terms that make up the
expression. To be clear, something like this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="p">(</span><span class="n">f_result</span><span class="p">()</span> <span class="o">==</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">])</span> <span class="k">as</span> <span class="n">res</span><span class="p">:</span>
</pre></div>
</div>
<p>seems awfully limited, when this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="p">(</span><span class="n">f_result</span><span class="p">()</span> <span class="k">as</span> <span class="n">res</span><span class="p">)</span> <span class="o">==</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]:</span>
</pre></div>
</div>
<p>is probably the desired result.</p>
</section>
<section id="use-cases">
<h2><a class="toc-backref" href="#use-cases" role="doc-backlink">Use Cases</a></h2>
<p>See the Examples section near the end.</p>
</section>
<section id="specification">
<h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2>
<p>A new expression is proposed with the (nominal) syntax:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">EXPR</span> <span class="o">-&gt;</span> <span class="n">VAR</span>
</pre></div>
</div>
<p>This single expression does the following:</p>
<ul class="simple">
<li>Evaluate the value of <code class="docutils literal notranslate"><span class="pre">EXPR</span></code>, an arbitrary expression;</li>
<li>Assign the result to <code class="docutils literal notranslate"><span class="pre">VAR</span></code>, a single assignment target; and</li>
<li>Leave the result of <code class="docutils literal notranslate"><span class="pre">EXPR</span></code> on the Top of Stack (TOS)</li>
</ul>
<p>Here <code class="docutils literal notranslate"><span class="pre">-&gt;</span></code> or (<code class="docutils literal notranslate"><span class="pre">RARROW</span></code>) has been used to illustrate the concept that
the result of <code class="docutils literal notranslate"><span class="pre">EXPR</span></code> is assigned to <code class="docutils literal notranslate"><span class="pre">VAR</span></code>.</p>
<p>The translation of the proposed syntax is:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">VAR</span> <span class="o">=</span> <span class="p">(</span><span class="n">EXPR</span><span class="p">)</span>
<span class="p">(</span><span class="n">EXPR</span><span class="p">)</span>
</pre></div>
</div>
<p>The assignment target can be either an attribute, a subscript or
name:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">f</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">name</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="c1"># where &#39;name&#39; exists previously.</span>
<span class="n">f</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">name</span><span class="o">.</span><span class="n">attr</span> <span class="c1"># again &#39;name&#39; exists prior to this expression.</span>
<span class="n">f</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">name</span>
</pre></div>
</div>
<p>This expression should be available anywhere that an expression is
currently accepted.</p>
<p>All exceptions that are currently raised during invalid
assignments will continue to be raised when using the assignment
expression. For example, a <code class="docutils literal notranslate"><span class="pre">NameError</span></code> will be raised when in
example 1 and 2 above if <code class="docutils literal notranslate"><span class="pre">name</span></code> is not previously defined, or an
<code class="docutils literal notranslate"><span class="pre">IndexError</span></code> if index 0 was out of range.</p>
</section>
<section id="examples-from-the-standard-library">
<h2><a class="toc-backref" href="#examples-from-the-standard-library" role="doc-backlink">Examples from the Standard Library</a></h2>
<p>The following two examples were chosen after a brief search
through the standard library, specifically both are from ast.py
which happened to be open at the time of the search.</p>
<p>Original:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">walk</span><span class="p">(</span><span class="n">node</span><span class="p">):</span>
<span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">deque</span>
<span class="n">todo</span> <span class="o">=</span> <span class="n">deque</span><span class="p">([</span><span class="n">node</span><span class="p">])</span>
<span class="k">while</span> <span class="n">todo</span><span class="p">:</span>
<span class="n">node</span> <span class="o">=</span> <span class="n">todo</span><span class="o">.</span><span class="n">popleft</span><span class="p">()</span>
<span class="n">todo</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">iter_child_nodes</span><span class="p">(</span><span class="n">node</span><span class="p">))</span>
<span class="k">yield</span> <span class="n">node</span>
</pre></div>
</div>
<p>Using assignment expression:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">walk</span><span class="p">(</span><span class="n">node</span><span class="p">):</span>
<span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">deque</span>
<span class="n">todo</span> <span class="o">=</span> <span class="n">deque</span><span class="p">([</span><span class="n">node</span><span class="p">])</span>
<span class="k">while</span> <span class="n">todo</span><span class="p">:</span>
<span class="n">todo</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">iter_child_nodes</span><span class="p">(</span><span class="n">todo</span><span class="o">.</span><span class="n">popleft</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">node</span><span class="p">))</span>
<span class="k">yield</span> <span class="n">node</span>
</pre></div>
</div>
<p>Original:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">get_docstring</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">clean</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="p">(</span><span class="n">FunctionDef</span><span class="p">,</span> <span class="n">ClassDef</span><span class="p">,</span> <span class="n">Module</span><span class="p">)):</span>
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s2">&quot;</span><span class="si">%r</span><span class="s2"> can&#39;t have docstrings&quot;</span>
<span class="o">%</span> <span class="n">node</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">)</span>
<span class="k">if</span> <span class="n">node</span><span class="o">.</span><span class="n">body</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">node</span><span class="o">.</span><span class="n">body</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">Expr</span><span class="p">)</span> <span class="ow">and</span> \
<span class="nb">isinstance</span><span class="p">(</span><span class="n">node</span><span class="o">.</span><span class="n">body</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">value</span><span class="p">,</span> <span class="n">Str</span><span class="p">):</span>
<span class="k">if</span> <span class="n">clean</span><span class="p">:</span>
<span class="kn">import</span> <span class="nn">inspect</span>
<span class="k">return</span> <span class="n">inspect</span><span class="o">.</span><span class="n">cleandoc</span><span class="p">(</span><span class="n">node</span><span class="o">.</span><span class="n">body</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">value</span><span class="o">.</span><span class="n">s</span><span class="p">)</span>
<span class="k">return</span> <span class="n">node</span><span class="o">.</span><span class="n">body</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">value</span><span class="o">.</span><span class="n">s</span>
</pre></div>
</div>
<p>Using assignment expression:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">get_docstring</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">clean</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="p">(</span><span class="n">FunctionDef</span><span class="p">,</span> <span class="n">ClassDef</span><span class="p">,</span> <span class="n">Module</span><span class="p">)):</span>
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s2">&quot;</span><span class="si">%r</span><span class="s2"> can&#39;t have docstrings&quot;</span>
<span class="o">%</span> <span class="n">node</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">)</span>
<span class="k">if</span> <span class="n">node</span><span class="o">.</span><span class="n">body</span> <span class="o">-&gt;</span> <span class="n">body</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">body</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">-&gt;</span> <span class="n">elem</span><span class="p">,</span> <span class="n">Expr</span><span class="p">)</span> <span class="ow">and</span> \
<span class="nb">isinstance</span><span class="p">(</span><span class="n">elem</span><span class="o">.</span><span class="n">value</span> <span class="o">-&gt;</span> <span class="n">value</span><span class="p">,</span> <span class="n">Str</span><span class="p">):</span>
<span class="k">if</span> <span class="n">clean</span><span class="p">:</span>
<span class="kn">import</span> <span class="nn">inspect</span>
<span class="k">return</span> <span class="n">inspect</span><span class="o">.</span><span class="n">cleandoc</span><span class="p">(</span><span class="n">value</span><span class="o">.</span><span class="n">s</span><span class="p">)</span>
<span class="k">return</span> <span class="n">value</span><span class="o">.</span><span class="n">s</span>
</pre></div>
</div>
</section>
<section id="examples">
<h2><a class="toc-backref" href="#examples" role="doc-backlink">Examples</a></h2>
<p>The examples shown below highlight some of the desirable features
of the assignment expression, and some of the possible corner
cases.</p>
<ol class="arabic">
<li>Assignment in an if statement for use later:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">expensive</span><span class="p">():</span>
<span class="kn">import</span> <span class="nn">time</span><span class="p">;</span> <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="k">return</span> <span class="s1">&#39;spam&#39;</span>
<span class="k">if</span> <span class="n">expensive</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">res</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">&#39;spam&#39;</span><span class="p">,</span> <span class="s1">&#39;eggs&#39;</span><span class="p">):</span>
<span class="n">dosomething</span><span class="p">(</span><span class="n">res</span><span class="p">)</span>
</pre></div>
</div>
</li>
<li>Assignment in a while loop clause:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">while</span> <span class="nb">len</span><span class="p">(</span><span class="n">expensive</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">res</span><span class="p">)</span> <span class="o">==</span> <span class="mi">4</span><span class="p">:</span>
<span class="n">dosomething</span><span class="p">(</span><span class="n">res</span><span class="p">)</span>
</pre></div>
</div>
</li>
<li>Keep the iterator object from the for loop:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">ch</span> <span class="ow">in</span> <span class="n">expensive</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">res</span><span class="p">:</span>
<span class="n">sell_on_internet</span><span class="p">(</span><span class="n">res</span><span class="p">)</span>
</pre></div>
</div>
</li>
<li>Corner case:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">ch</span> <span class="o">-&gt;</span> <span class="n">please_dont</span> <span class="ow">in</span> <span class="n">expensive</span><span class="p">():</span>
<span class="k">pass</span>
<span class="c1"># who would want to do this? Not I.</span>
</pre></div>
</div>
</li>
</ol>
</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="id2" role="doc-footnote">
<dt class="label" id="id2">[<a href="#id1">1</a>]</dt>
<dd>Issue1714448 “if something as x:”, k0wax
<a class="reference external" href="http://bugs.python.org/issue1714448">http://bugs.python.org/issue1714448</a></aside>
</aside>
</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-0379.rst">https://github.com/python/peps/blob/main/peps/pep-0379.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0379.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="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#motivation-and-summary">Motivation and Summary</a></li>
<li><a class="reference internal" href="#use-cases">Use Cases</a></li>
<li><a class="reference internal" href="#specification">Specification</a></li>
<li><a class="reference internal" href="#examples-from-the-standard-library">Examples from the Standard Library</a></li>
<li><a class="reference internal" href="#examples">Examples</a></li>
<li><a class="reference internal" href="#references">References</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-0379.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>