737 lines
57 KiB
HTML
737 lines
57 KiB
HTML
|
||
<!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 736 – Shorthand syntax for keyword arguments at invocation | peps.python.org</title>
|
||
<link rel="shortcut icon" href="../_static/py.png">
|
||
<link rel="canonical" href="https://peps.python.org/pep-0736/">
|
||
<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 736 – Shorthand syntax for keyword arguments at invocation | peps.python.org'>
|
||
<meta property="og:description" content="This PEP proposes introducing syntactic sugar f(x=) for the pattern where a named argument is the same as the name of the variable corresponding to its value f(x=x).">
|
||
<meta property="og:type" content="website">
|
||
<meta property="og:url" content="https://peps.python.org/pep-0736/">
|
||
<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 proposes introducing syntactic sugar f(x=) for the pattern where a named argument is the same as the name of the variable corresponding to its value f(x=x).">
|
||
<meta name="theme-color" content="#3776ab">
|
||
</head>
|
||
<body>
|
||
|
||
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
|
||
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
|
||
<title>Following system colour scheme</title>
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<circle cx="12" cy="12" r="9"></circle>
|
||
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
|
||
</svg>
|
||
</symbol>
|
||
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
|
||
<title>Selected dark colour scheme</title>
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
|
||
</svg>
|
||
</symbol>
|
||
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
|
||
<title>Selected light colour scheme</title>
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<circle cx="12" cy="12" r="5"></circle>
|
||
<line x1="12" y1="1" x2="12" y2="3"></line>
|
||
<line x1="12" y1="21" x2="12" y2="23"></line>
|
||
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
||
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
||
<line x1="1" y1="12" x2="3" y2="12"></line>
|
||
<line x1="21" y1="12" x2="23" y2="12"></line>
|
||
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
||
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
||
</svg>
|
||
</symbol>
|
||
</svg>
|
||
<script>
|
||
|
||
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
|
||
</script>
|
||
<section id="pep-page-section">
|
||
<header>
|
||
<h1>Python Enhancement Proposals</h1>
|
||
<ul class="breadcrumbs">
|
||
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> » </li>
|
||
<li><a href="../pep-0000/">PEP Index</a> » </li>
|
||
<li>PEP 736</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 736 – Shorthand syntax for keyword arguments at invocation</h1>
|
||
<dl class="rfc2822 field-list simple">
|
||
<dt class="field-odd">Author<span class="colon">:</span></dt>
|
||
<dd class="field-odd">Joshua Bambrick <jbambrick at google.com>,
|
||
Chris Angelico <rosuav at gmail.com></dd>
|
||
<dt class="field-even">Discussions-To<span class="colon">:</span></dt>
|
||
<dd class="field-even"><a class="reference external" href="https://discuss.python.org/t/pep-736-shorthand-syntax-for-keyword-arguments-at-invocation/43432">Discourse thread</a></dd>
|
||
<dt class="field-odd">Status<span class="colon">:</span></dt>
|
||
<dd class="field-odd"><abbr title="Proposal under active discussion and revision">Draft</abbr></dd>
|
||
<dt class="field-even">Type<span class="colon">:</span></dt>
|
||
<dd class="field-even"><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-odd">Created<span class="colon">:</span></dt>
|
||
<dd class="field-odd">28-Nov-2023</dd>
|
||
<dt class="field-even">Python-Version<span class="colon">:</span></dt>
|
||
<dd class="field-even">3.14</dd>
|
||
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
|
||
<dd class="field-odd"><a class="reference external" href="https://discuss.python.org/t/syntactic-sugar-to-encourage-use-of-named-arguments/36217" title="Discourse thread">14-Oct-2023</a>,
|
||
<a class="reference external" href="https://discuss.python.org/t/pep-736-shorthand-syntax-for-keyword-arguments-at-invocation/43432" title="Discourse thread">17-Jan-2024</a></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">Motivation</a></li>
|
||
<li><a class="reference internal" href="#rationale">Rationale</a><ul>
|
||
<li><a class="reference internal" href="#encourages-use-of-named-arguments">Encourages use of named arguments</a></li>
|
||
<li><a class="reference internal" href="#reduces-verbosity">Reduces verbosity</a></li>
|
||
<li><a class="reference internal" href="#encourages-consistent-variable-names">Encourages consistent variable names</a></li>
|
||
<li><a class="reference internal" href="#highlights-arguments-not-following-this-pattern">Highlights arguments not following this pattern</a></li>
|
||
<li><a class="reference internal" href="#applicability-to-dictionary-construction">Applicability to dictionary construction</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#specification">Specification</a></li>
|
||
<li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li>
|
||
<li><a class="reference internal" href="#security-implications">Security Implications</a></li>
|
||
<li><a class="reference internal" href="#prior-art">Prior Art</a></li>
|
||
<li><a class="reference internal" href="#applicability">Applicability</a></li>
|
||
<li><a class="reference internal" href="#proposed-syntax">Proposed Syntax</a></li>
|
||
<li><a class="reference internal" href="#how-to-teach-this">How to Teach This</a></li>
|
||
<li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a><ul>
|
||
<li><a class="reference internal" href="#f-a-b-x"><code class="docutils literal notranslate"><span class="pre">f(a,</span> <span class="pre">b,</span> <span class="pre">*,</span> <span class="pre">x)</span></code></a></li>
|
||
<li><a class="reference internal" href="#f-x"><code class="docutils literal notranslate"><span class="pre">f(=x)</span></code></a></li>
|
||
<li><a class="reference internal" href="#f-x-or-f-x-or-f-x"><code class="docutils literal notranslate"><span class="pre">f(%x)</span></code> or <code class="docutils literal notranslate"><span class="pre">f(:x)</span></code> or <code class="docutils literal notranslate"><span class="pre">f(.x)</span></code></a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#objections">Objections</a><ul>
|
||
<li><a class="reference internal" href="#the-syntax-is-ugly">The syntax is ugly</a></li>
|
||
<li><a class="reference internal" href="#the-feature-is-confusing">The feature is confusing</a></li>
|
||
<li><a class="reference internal" href="#the-feature-is-not-explicit">The feature is not explicit</a></li>
|
||
<li><a class="reference internal" href="#the-feature-adds-another-way-of-doing-things">The feature adds another way of doing things</a></li>
|
||
<li><a class="reference internal" href="#renaming-the-variable-in-the-calling-context-will-break-the-code">Renaming the variable in the calling context will break the code</a></li>
|
||
<li><a class="reference internal" href="#this-syntax-increases-coupling">This syntax increases coupling</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#recommendations-for-using-this-syntax">Recommendations for using this syntax</a></li>
|
||
<li><a class="reference internal" href="#impact-on-editing">Impact on editing</a><ul>
|
||
<li><a class="reference internal" href="#using-a-plain-text-editor">Using a plain text editor</a></li>
|
||
<li><a class="reference internal" href="#proposals-for-ides">Proposals for IDEs</a><ul>
|
||
<li><a class="reference internal" href="#highlighting-nameerrors">Highlighting NameErrors</a></li>
|
||
<li><a class="reference internal" href="#jump-to-definition">Jump to definition</a></li>
|
||
<li><a class="reference internal" href="#highlighting-other-references">Highlighting other references</a></li>
|
||
<li><a class="reference internal" href="#rename-symbol">Rename symbol</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</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 proposes introducing syntactic sugar <code class="docutils literal notranslate"><span class="pre">f(x=)</span></code> for the pattern
|
||
where a named argument is the same as the name of the variable corresponding to
|
||
its value <code class="docutils literal notranslate"><span class="pre">f(x=x)</span></code>.</p>
|
||
</section>
|
||
<section id="motivation">
|
||
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
|
||
<p>Keyword argument syntax can become needlessly repetitive and verbose.</p>
|
||
<p>Consider the following call:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">my_function</span><span class="p">(</span>
|
||
<span class="n">my_first_variable</span><span class="o">=</span><span class="n">my_first_variable</span><span class="p">,</span>
|
||
<span class="n">my_second_variable</span><span class="o">=</span><span class="n">my_second_variable</span><span class="p">,</span>
|
||
<span class="n">my_third_variable</span><span class="o">=</span><span class="n">my_third_variable</span><span class="p">,</span>
|
||
<span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The case of a keyword argument name matching the variable name of its value is
|
||
prevalent among Python libraries. This verbosity and redundancy discourages
|
||
use of named arguments and reduces readability by increasing visual noise.</p>
|
||
</section>
|
||
<section id="rationale">
|
||
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
|
||
<p>There are two ways to invoke a function with arguments: by position and by
|
||
keyword. Keyword arguments confer many benefits by being explicit, thus
|
||
increasing readability and minimising the risk of inadvertent transposition. On
|
||
the flipside, positional arguments are often used simply to minimise verbosity
|
||
and visual noise.</p>
|
||
<p>We contend that a simple syntactic sugar used to simplify this common pattern
|
||
which would confer numerous benefits:</p>
|
||
<section id="encourages-use-of-named-arguments">
|
||
<h3><a class="toc-backref" href="#encourages-use-of-named-arguments" role="doc-backlink">Encourages use of named arguments</a></h3>
|
||
<p>This syntax would encourage the use of named arguments, thereby increasing
|
||
readability and reducing bugs from argument transposition.</p>
|
||
</section>
|
||
<section id="reduces-verbosity">
|
||
<h3><a class="toc-backref" href="#reduces-verbosity" role="doc-backlink">Reduces verbosity</a></h3>
|
||
<p>By minimising visual noise and in some cases lines of code, we can increase
|
||
readability.</p>
|
||
</section>
|
||
<section id="encourages-consistent-variable-names">
|
||
<h3><a class="toc-backref" href="#encourages-consistent-variable-names" role="doc-backlink">Encourages consistent variable names</a></h3>
|
||
<p>A common problem is that semantically identical variables have different names
|
||
depending on their contexts. This syntax would encourage authors to use the same
|
||
variable name when calling a function as the argument name, which would increase
|
||
consistency of variable names used and hence also readability.</p>
|
||
</section>
|
||
<section id="highlights-arguments-not-following-this-pattern">
|
||
<h3><a class="toc-backref" href="#highlights-arguments-not-following-this-pattern" role="doc-backlink">Highlights arguments not following this pattern</a></h3>
|
||
<p>With the current syntax, function calls where many arguments are forwarded from
|
||
the local context can make other argument values easy to miss due to the visual
|
||
noise. For example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">add_middleware</span><span class="p">(</span>
|
||
<span class="n">excluded_urls</span><span class="o">=</span><span class="n">excluded_urls</span><span class="p">,</span>
|
||
<span class="n">server_request</span><span class="o">=</span><span class="n">server_request</span><span class="p">,</span>
|
||
<span class="n">client_request</span><span class="o">=</span><span class="n">client_request</span><span class="p">,</span>
|
||
<span class="n">client_response</span><span class="o">=</span><span class="n">client_response</span><span class="p">,</span>
|
||
<span class="n">span_details</span><span class="o">=</span><span class="n">_get_span_details</span><span class="p">(),</span>
|
||
<span class="n">tracer</span><span class="o">=</span><span class="n">tracer</span><span class="p">,</span>
|
||
<span class="n">meter</span><span class="o">=</span><span class="n">meter</span><span class="p">,</span>
|
||
<span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>With this syntax, the exceptional arguments become easier to identify:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">add_middleware</span><span class="p">(</span>
|
||
<span class="n">excluded_urls</span><span class="o">=</span><span class="p">,</span>
|
||
<span class="n">server_request</span><span class="o">=</span><span class="p">,</span>
|
||
<span class="n">client_request</span><span class="o">=</span><span class="p">,</span>
|
||
<span class="n">client_response</span><span class="o">=</span><span class="p">,</span>
|
||
<span class="n">span_details</span><span class="o">=</span><span class="n">_get_span_details</span><span class="p">(),</span>
|
||
<span class="n">tracer</span><span class="o">=</span><span class="p">,</span>
|
||
<span class="n">meter</span><span class="o">=</span><span class="p">,</span>
|
||
<span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="applicability-to-dictionary-construction">
|
||
<h3><a class="toc-backref" href="#applicability-to-dictionary-construction" role="doc-backlink">Applicability to dictionary construction</a></h3>
|
||
<p>This syntax can be applied to dictionary construction where a similar pattern
|
||
frequently occurs (where dictionary keys are identical the names of the
|
||
variables assigned as their values), <code class="docutils literal notranslate"><span class="pre">{"x":</span> <span class="pre">x,</span> <span class="pre">"y":</span> <span class="pre">y}</span></code> or <code class="docutils literal notranslate"><span class="pre">dict(x=x,</span> <span class="pre">y=y)</span></code>.
|
||
With this feature, this can now also be trivially written as <code class="docutils literal notranslate"><span class="pre">dict(x=,</span> <span class="pre">y=)</span></code>.
|
||
Whether to further support similar syntax in dictionary literals is an open
|
||
question out of the scope of this PEP.</p>
|
||
</section>
|
||
</section>
|
||
<section id="specification">
|
||
<h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2>
|
||
<p>We propose to introduce syntactic sugar such that, if the value of a keyword
|
||
argument is omitted from a function invocation, the argument’s value is inferred
|
||
to be the variable matching that name at the invocation scope.</p>
|
||
<p>For example, the function invocation:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">my_function</span><span class="p">(</span><span class="n">my_first_variable</span><span class="o">=</span><span class="p">,</span> <span class="n">my_second_variable</span><span class="o">=</span><span class="p">,</span> <span class="n">my_third_variable</span><span class="o">=</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Will be interpreted exactly equivalently to following in existing syntax:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">my_function</span><span class="p">(</span>
|
||
<span class="n">my_first_variable</span><span class="o">=</span><span class="n">my_first_variable</span><span class="p">,</span>
|
||
<span class="n">my_second_variable</span><span class="o">=</span><span class="n">my_second_variable</span><span class="p">,</span>
|
||
<span class="n">my_third_variable</span><span class="o">=</span><span class="n">my_third_variable</span><span class="p">,</span>
|
||
<span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>If no variable matches that name in the invocation scope, a <code class="docutils literal notranslate"><span class="pre">NameError</span></code> is
|
||
raised in an identical manner as would be with the established expanded syntax.</p>
|
||
<p>This proposal only pertains to function invocations; function definitions are
|
||
unaffected by the syntax change. All existing valid syntax is unchanged.</p>
|
||
</section>
|
||
<section id="backwards-compatibility">
|
||
<h2><a class="toc-backref" href="#backwards-compatibility" role="doc-backlink">Backwards Compatibility</a></h2>
|
||
<p>Only new syntax is added which was previously syntactically erroneous. No
|
||
existing valid syntax is modified. As such, the changes proposed are fully
|
||
backwards compatible.</p>
|
||
</section>
|
||
<section id="security-implications">
|
||
<h2><a class="toc-backref" href="#security-implications" role="doc-backlink">Security Implications</a></h2>
|
||
<p>There are no security implications for this change.</p>
|
||
</section>
|
||
<section id="prior-art">
|
||
<h2><a class="toc-backref" href="#prior-art" role="doc-backlink">Prior Art</a></h2>
|
||
<p>Python already possesses a very similar feature in f-string interpolation where
|
||
<code class="docutils literal notranslate"><span class="pre">f'{x=}'</span></code> is effectively expanded to <code class="docutils literal notranslate"><span class="pre">f'x={x}'</span></code> (see
|
||
<a class="reference external" href="https://github.com/python/cpython/issues/80998">related GitHub issue</a>).</p>
|
||
<p>Several modern languages provide similar features during function invocation,
|
||
sometimes referred to as ‘punning’. For example:</p>
|
||
<ul class="simple">
|
||
<li>In Ruby, <code class="docutils literal notranslate"><span class="pre">f(x:,</span> <span class="pre">y:)</span></code> is syntactic sugar for <code class="docutils literal notranslate"><span class="pre">f(x:</span> <span class="pre">x,</span> <span class="pre">y:</span> <span class="pre">y)</span></code>. See the
|
||
<a class="reference external" href="https://www.ruby-lang.org/en/news/2021/12/25/ruby-3-1-0-released/#:~:text=Other%20Notable%20New%20Features">Ruby 3.1.0 release notes</a> (search for “keyword arguments”).</li>
|
||
<li>In ReasonML, <code class="docutils literal notranslate"><span class="pre">f(~x,</span> <span class="pre">~y)</span></code> is syntactic sugar for <code class="docutils literal notranslate"><span class="pre">f(~x=x,</span> <span class="pre">~y=y)</span></code>. See the
|
||
<a class="reference external" href="https://reasonml.github.io/docs/en/function#function-application">ReasonML function documentation</a> (search for “punning”).</li>
|
||
<li>In SystemVerilog, <code class="docutils literal notranslate"><span class="pre">(.mult,</span> <span class="pre">.mop1,</span> <span class="pre">.data);</span></code> is syntactic sugar for
|
||
<code class="docutils literal notranslate"><span class="pre">(.mult(mult),</span> <span class="pre">.mop1(mop1),</span>  <span class="pre">.data(data));</span></code>. See
|
||
<a class="reference external" href="http://www.sunburst-design.com/papers/CummingsDesignCon2005_SystemVerilog_ImplicitPorts.pdf">SystemVerilog Implicit Port Connections</a>.</li>
|
||
<li>In Jakt, <code class="docutils literal notranslate"><span class="pre">f(x,</span> <span class="pre">y)</span></code> is syntactic sugar for <code class="docutils literal notranslate"><span class="pre">f(x:</span> <span class="pre">x,</span> <span class="pre">y:</span> <span class="pre">y)</span></code>. See
|
||
<a class="reference external" href="https://github.com/SerenityOS/jakt?tab=readme-ov-file#function-calls">The Jakt programming language</a>.</li>
|
||
</ul>
|
||
<p>Beyond function invocation specifically, more languages offer similar features:</p>
|
||
<ul class="simple">
|
||
<li>In OCaml, <code class="docutils literal notranslate"><span class="pre">let+</span> <span class="pre">x</span> <span class="pre">in</span> <span class="pre">…</span></code> is syntactic sugar for <code class="docutils literal notranslate"><span class="pre">let+</span> <span class="pre">x</span> <span class="pre">=</span> <span class="pre">x</span> <span class="pre">in</span> <span class="pre">…</span></code>. See
|
||
<a class="reference external" href="https://v2.ocaml.org/manual/bindingops.html#ss:letops-punning">OCaml Short notation for variable bindings (let-punning)</a>.</li>
|
||
<li>In JavaScript, <code class="docutils literal notranslate"><span class="pre">{</span> <span class="pre">x,</span> <span class="pre">y</span> <span class="pre">}</span></code> is syntactic sugar for <code class="docutils literal notranslate"><span class="pre">{x:</span> <span class="pre">x,</span> <span class="pre">y:</span> <span class="pre">y}</span></code>. See
|
||
<a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer">JavaScript Object Initializer</a>.</li>
|
||
<li>In Rust, <code class="docutils literal notranslate"><span class="pre">User</span> <span class="pre">{</span> <span class="pre">x,</span> <span class="pre">y</span> <span class="pre">}</span></code> is shorthand for <code class="docutils literal notranslate"><span class="pre">User</span> <span class="pre">{x:</span> <span class="pre">x,</span> <span class="pre">y:</span> <span class="pre">y}</span></code>. See
|
||
<a class="reference external" href="https://doc.rust-lang.org/book/ch05-01-defining-structs.html#using-the-field-init-shorthand-when-variables-and-fields-have-the-same-name">Rust Using the Field Init Shorthand</a>.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="applicability">
|
||
<h2><a class="toc-backref" href="#applicability" role="doc-backlink">Applicability</a></h2>
|
||
<p>We analysed popular Python libraries from the last few years using
|
||
<a class="reference external" href="https://gist.github.com/joshuabambrick/a850d0e0050129b9252c748fa06c48b2">this script</a>
|
||
to compute:</p>
|
||
<ul class="simple">
|
||
<li>The number of keyword arguments were of the form <code class="docutils literal notranslate"><span class="pre">f(x=x)</span></code> at invocation.</li>
|
||
<li>The percentage of keyword arguments which had the form <code class="docutils literal notranslate"><span class="pre">f(x=x)</span></code> at
|
||
invocation.</li>
|
||
<li>The number of lines of code which could be saved by using this syntactic sugar
|
||
to reduce the need for line wraps.</li>
|
||
</ul>
|
||
<p>The purpose of this exercise was to compute statistics about the prevalence of
|
||
this pattern and should not be interpreted as a recommendation that the proposed
|
||
syntactic sugar should be applied universally.</p>
|
||
<table class="docutils align-default">
|
||
<thead>
|
||
<tr class="row-odd"><th class="head">Statistic</th>
|
||
<th class="head"><a class="reference external" href="https://github.com/joshuabambrick/polars/pull/1">polars</a></th>
|
||
<th class="head"><a class="reference external" href="https://github.com/joshuabambrick/fastapi/pull/1">fastapi</a></th>
|
||
<th class="head"><a class="reference external" href="https://github.com/joshuabambrick/rich/pull/1">rich</a></th>
|
||
<th class="head"><a class="reference external" href="https://github.com/joshuabambrick/httpx/pull/1">httpx</a></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="row-even"><td>Number of keyword arguments of the form <code class="docutils literal notranslate"><span class="pre">f(x=x)</span></code> at invocation</td>
|
||
<td>1,654</td>
|
||
<td>1,408</td>
|
||
<td>566</td>
|
||
<td>759</td>
|
||
</tr>
|
||
<tr class="row-odd"><td>Percentage of keyword arguments of the form <code class="docutils literal notranslate"><span class="pre">f(x=x)</span></code> at invocation</td>
|
||
<td>15.83%</td>
|
||
<td>28.11%</td>
|
||
<td>15.74%</td>
|
||
<td>45.13%</td>
|
||
</tr>
|
||
<tr class="row-even"><td>Lines saved</td>
|
||
<td>170</td>
|
||
<td>35</td>
|
||
<td>62</td>
|
||
<td>117</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Based on this, we note that the <code class="docutils literal notranslate"><span class="pre">f(x=x)</span></code> keyword argument pattern is
|
||
widespread, accounting for anywhere from 15% to just below half of all keyword
|
||
argument uses depending on the codebase.</p>
|
||
</section>
|
||
<section id="proposed-syntax">
|
||
<h2><a class="toc-backref" href="#proposed-syntax" role="doc-backlink">Proposed Syntax</a></h2>
|
||
<p>While this feature has been proposed on numerous occasions with several
|
||
different forms <a class="footnote-reference brackets" href="#id13" id="id1">[1]</a> <a class="footnote-reference brackets" href="#id14" id="id2">[2]</a> <a class="footnote-reference brackets" href="#id15" id="id3">[3]</a> <a class="footnote-reference brackets" href="#id16" id="id4">[4]</a> <a class="footnote-reference brackets" href="#id17" id="id5">[5]</a>, <a class="footnote-reference brackets" href="#id18" id="id6">[6]</a> we have opted to advocate
|
||
for the <code class="docutils literal notranslate"><span class="pre">f(x=)</span></code> form for the following reasons:</p>
|
||
<ul class="simple">
|
||
<li>This feature has been proposed frequently over a ten year period with the
|
||
<code class="docutils literal notranslate"><span class="pre">f(x=)</span></code> or <code class="docutils literal notranslate"><span class="pre">f(=x)</span></code> being by far the most common syntax <a class="footnote-reference brackets" href="#id13" id="id7">[1]</a> <a class="footnote-reference brackets" href="#id14" id="id8">[2]</a> <a class="footnote-reference brackets" href="#id18" id="id9">[6]</a>.
|
||
This is a strong indicator that it is the obvious notation.</li>
|
||
<li>The proposed syntax closely matches the f-string debug <code class="docutils literal notranslate"><span class="pre">f'{var=}'</span></code> syntax
|
||
(established Pythonic style) and serves an almost identical purpose.</li>
|
||
<li>The proposed syntax is exactly analogous to the Ruby keyword argument
|
||
syntactic sugar. See the
|
||
<a class="reference external" href="https://www.ruby-lang.org/en/news/2021/12/25/ruby-3-1-0-released/#:~:text=Other%20Notable%20New%20Features">Ruby 3.1.0 release notes</a> (search for “keyword arguments”).</li>
|
||
<li>The syntax is easy to implement as it is simple syntactic sugar.</li>
|
||
<li>When compared to the prefix form (see <a class="reference internal" href="#rejected-ideas">Rejected Ideas</a>), this syntax
|
||
communicates “here is a parameter, go find its argument” which is more
|
||
appropriate given the semantics of named arguments.</li>
|
||
<li><a class="reference external" href="https://discuss.python.org/t/syntactic-sugar-to-encourage-use-of-named-arguments/36217/130">A poll of Python developers</a>
|
||
indicates that this is the most popular syntax among those proposed.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="how-to-teach-this">
|
||
<h2><a class="toc-backref" href="#how-to-teach-this" role="doc-backlink">How to Teach This</a></h2>
|
||
<p>To ease the communication of and search for this feature, it may also be
|
||
valuable to provide this feature with a name, such as ‘keyword argument
|
||
shorthand’.</p>
|
||
<p>Keen Python developers will likely hear about this feature through typical
|
||
information channels, such as newsboards, social media, mailing lists, online
|
||
forums, or word of mouth. Many more will encounter this feature while reading
|
||
code and noting the omission of the value in a keyword argument at invocation,
|
||
violating their expectations. We should ensure such developers have easy access
|
||
to documentation that explains the semantics of this feature and that this
|
||
documentation is easy to find when searching. For example, the
|
||
<a class="reference external" href="https://docs.python.org/3/glossary.html#term-argument">Python Glossary</a> and
|
||
<a class="reference external" href="https://docs.python.org/3/tutorial/controlflow.html#keyword-arguments">Tutorial</a>
|
||
may be updated accordingly and reasonable keywords may be used to help with
|
||
search discoverability.
|
||
<a class="reference external" href="https://stackoverflow.blog/2011/07/01/its-ok-to-ask-and-answer-your-own-questions/">A StackOverflow question</a>
|
||
could be written to help explain this feature to those searching for an
|
||
explanation.</p>
|
||
<p>A teacher may explain this feature to new Python programmers as, “where you see
|
||
an argument followed by an equals sign, such as <code class="docutils literal notranslate"><span class="pre">f(x=)</span></code>, this represents a
|
||
keyword argument where the name of the argument and its value are the same. This
|
||
can be written equivalently in the expanded notation, <code class="docutils literal notranslate"><span class="pre">f(x=x)</span></code>.” Depending on
|
||
a student’s background, a teacher might further compare this to equivalent
|
||
syntax in other languages or Python’s f-string syntax <code class="docutils literal notranslate"><span class="pre">f"{x=}"</span></code>.</p>
|
||
<p>To understand this, a student of Python would need to be familiar with the
|
||
basics of functions in addition to the existing keyword argument syntax.
|
||
Given that this feature is a relatively straightforward syntactic sugar, it is
|
||
reasonable that a student who possesses a grasp of keyword arguments will be
|
||
able to absorb this concept quickly. This is evidenced by the success of the
|
||
f-string syntax as well as similar features in other languages (see
|
||
<a class="reference internal" href="#prior-art">Prior Art</a>).</p>
|
||
</section>
|
||
<section id="rejected-ideas">
|
||
<h2><a class="toc-backref" href="#rejected-ideas" role="doc-backlink">Rejected Ideas</a></h2>
|
||
<p>Many alternative syntaxes have been proposed however no syntax other than
|
||
<code class="docutils literal notranslate"><span class="pre">f(=x)</span></code> or <code class="docutils literal notranslate"><span class="pre">f(x=)</span></code> has garnered significant support. We here enumerate some
|
||
of the most popular proposed alternatives and why we ultimately reject them.</p>
|
||
<section id="f-a-b-x">
|
||
<h3><a class="toc-backref" href="#f-a-b-x" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">f(a,</span> <span class="pre">b,</span> <span class="pre">*,</span> <span class="pre">x)</span></code></a></h3>
|
||
<p>On a few occasions the idea has been floated to borrow the syntax from
|
||
keyword-only function definitions.</p>
|
||
<p>In favour of this proposal:</p>
|
||
<ul class="simple">
|
||
<li>This syntax is familiar from its use to require keyword-only arguments in
|
||
function definitions.</li>
|
||
<li><a class="reference external" href="https://discuss.python.org/t/syntactic-sugar-to-encourage-use-of-named-arguments/36217/130">A poll of Python developers</a>
|
||
indicates that this is the second most popular syntax among those proposed.</li>
|
||
</ul>
|
||
<p>However, we object that:</p>
|
||
<ul class="simple">
|
||
<li>For any given argument, it is less clear from local context whether it is
|
||
positional or named. The <code class="docutils literal notranslate"><span class="pre">*</span></code> could easily be missed in a long argument list
|
||
and named arguments may be read as positional or vice versa.</li>
|
||
<li>It is unclear whether keyword arguments for which the value was not elided may
|
||
follow the <code class="docutils literal notranslate"><span class="pre">*</span></code>. If so, then their relative position will be confusingly
|
||
arbitrary, but if not, then an arbitrary grouping is enforced between
|
||
different types of keyword arguments and reordering of arguments would be
|
||
necessary if only one name (the argument or its value) was changed.</li>
|
||
<li>The use of <code class="docutils literal notranslate"><span class="pre">*</span></code> in function calls is established and this proposal would
|
||
introduce a new effect which could cause confusion. For example,
|
||
<code class="docutils literal notranslate"><span class="pre">f(a,</span> <span class="pre">*x,</span> <span class="pre">y)</span></code> would mean something different than <code class="docutils literal notranslate"><span class="pre">f(a,</span> <span class="pre">*,</span> <span class="pre">x,</span> <span class="pre">y)</span></code>.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="f-x">
|
||
<h3><a class="toc-backref" href="#f-x" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">f(=x)</span></code></a></h3>
|
||
<p>In favour of this form:</p>
|
||
<ul class="simple">
|
||
<li>The prefix operator is more similar to the established <code class="docutils literal notranslate"><span class="pre">*args</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> syntax for function calls.</li>
|
||
<li>It draws more attention to itself when arguments are arranged vertically. In
|
||
particular, if the arguments are of different lengths it is harder to find the
|
||
equal sign at the end. Moreover, since Python is read left to right, the use
|
||
of this feature is clearer to the reader earlier on.</li>
|
||
</ul>
|
||
<p>On the contrary:</p>
|
||
<ul class="simple">
|
||
<li>While the prefix version is visually louder, in practice, there is no need for
|
||
this feature to shout its presence any more than a typical named argument. By
|
||
the time we read to the <code class="docutils literal notranslate"><span class="pre">=</span></code> it is clear that the value is filled in
|
||
automatically just as the value is clear in the typical keyword argument case.</li>
|
||
<li>Semantically, this form communicates ‘here is a value, fill in the parameter’
|
||
which is not what we want to convey.</li>
|
||
<li>It is less similar to f-string syntax.</li>
|
||
<li>It is less obvious that arbitrary expressions are invalid, e.g. <code class="docutils literal notranslate"><span class="pre">f(=a</span> <span class="pre">+</span> <span class="pre">b)</span></code>.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="f-x-or-f-x-or-f-x">
|
||
<h3><a class="toc-backref" href="#f-x-or-f-x-or-f-x" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">f(%x)</span></code> or <code class="docutils literal notranslate"><span class="pre">f(:x)</span></code> or <code class="docutils literal notranslate"><span class="pre">f(.x)</span></code></a></h3>
|
||
<p>Several flavours of this syntax have been proposed with the prefix form
|
||
substituting another character for <code class="docutils literal notranslate"><span class="pre">=</span></code>. However, no such form has gained
|
||
traction and the choice of symbol seems arbitrary compared to <code class="docutils literal notranslate"><span class="pre">=</span></code>.
|
||
Additionally, there is less precedent in terms of existing language features
|
||
(such as f-string) or other languages (such as Ruby).</p>
|
||
</section>
|
||
</section>
|
||
<section id="objections">
|
||
<h2><a class="toc-backref" href="#objections" role="doc-backlink">Objections</a></h2>
|
||
<p>There are only a few hard objections to the introduction of this syntactic
|
||
sugar. Most of those not in favour of this feature are in the camp of ‘I
|
||
wouldn’t use it’. However, over the extensive conversations about this feature,
|
||
the following objections were the most common:</p>
|
||
<section id="the-syntax-is-ugly">
|
||
<h3><a class="toc-backref" href="#the-syntax-is-ugly" role="doc-backlink">The syntax is ugly</a></h3>
|
||
<p>This objection is by far the most common. On the contrary, we argue that:</p>
|
||
<ul class="simple">
|
||
<li>This objection is subjective and many community members disagree.</li>
|
||
<li>A nearly-identical syntax is already established for f-strings.</li>
|
||
<li>Programmers will, as ever, adjust over time.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="the-feature-is-confusing">
|
||
<h3><a class="toc-backref" href="#the-feature-is-confusing" role="doc-backlink">The feature is confusing</a></h3>
|
||
<p>We argue that:</p>
|
||
<ul class="simple">
|
||
<li>Introducing new features typically has this impact temporarily.</li>
|
||
<li>The syntax is very similar to the established <code class="docutils literal notranslate"><span class="pre">f'{x=}'</span></code> syntax.</li>
|
||
<li>The feature and syntax are familiar from other popular modern languages.</li>
|
||
<li>The expansion of <code class="docutils literal notranslate"><span class="pre">x=</span></code> to <code class="docutils literal notranslate"><span class="pre">x=x</span></code> is in fact a trivial feature and inherently
|
||
significantly less complex than <code class="docutils literal notranslate"><span class="pre">*arg</span></code> and <code class="docutils literal notranslate"><span class="pre">**kwarg</span></code> expansion.</li>
|
||
<li>This particular syntactic form has been independently proposed on numerous
|
||
occasions, indicating that it is the most obvious <a class="footnote-reference brackets" href="#id13" id="id10">[1]</a> <a class="footnote-reference brackets" href="#id14" id="id11">[2]</a> <a class="footnote-reference brackets" href="#id18" id="id12">[6]</a>.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="the-feature-is-not-explicit">
|
||
<h3><a class="toc-backref" href="#the-feature-is-not-explicit" role="doc-backlink">The feature is not explicit</a></h3>
|
||
<p>We recognise that, in an obvious sense, the argument value is ‘implicit’ in this
|
||
proposed syntax. However, we do not think that this is what the Zen of Python is
|
||
aiming to discourage.</p>
|
||
<p>In the sense that we take the Zen to be referring to, keyword arguments (for
|
||
example) are more explicit than positional arguments where the argument name is
|
||
omitted and impossible to tell from the local context. Conversely, the syntactic
|
||
sugar for integers <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">+=</span> <span class="pre">1</span></code> is not more implicit than <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">=</span> <span class="pre">x</span> <span class="pre">+</span> <span class="pre">1</span></code> in this
|
||
sense, even though the variable is omitted from the right hand side, because it
|
||
is immediately obvious from the local context what it is.</p>
|
||
<p>The syntax proposed in this PEP is much more closely analogous to the <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">+=</span> <span class="pre">1</span></code>
|
||
example (although simpler since we do not propose to introduce a new operation).
|
||
Moreover, the introduction of this syntactic sugar should encourage the use of
|
||
keyword arguments over positional ones, making typical Python codebases more
|
||
explicit in general.</p>
|
||
</section>
|
||
<section id="the-feature-adds-another-way-of-doing-things">
|
||
<h3><a class="toc-backref" href="#the-feature-adds-another-way-of-doing-things" role="doc-backlink">The feature adds another way of doing things</a></h3>
|
||
<p>The same argument can be made against all syntax changes. This is a simple
|
||
syntactic sugar, much as <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">+=</span> <span class="pre">1</span></code> is sugar for <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">=</span> <span class="pre">x</span> <span class="pre">+</span> <span class="pre">1</span></code> when <code class="docutils literal notranslate"><span class="pre">x</span></code> is an
|
||
integer. This isn’t tantamount to a ‘new way’ of passing arguments but a more
|
||
readable notation for the same way.</p>
|
||
</section>
|
||
<section id="renaming-the-variable-in-the-calling-context-will-break-the-code">
|
||
<h3><a class="toc-backref" href="#renaming-the-variable-in-the-calling-context-will-break-the-code" role="doc-backlink">Renaming the variable in the calling context will break the code</a></h3>
|
||
<p>A <code class="docutils literal notranslate"><span class="pre">NameError</span></code> would make the mistake clear in most cases. There may be
|
||
confusion if a variable from a broader scope has the same name as the original
|
||
variable, so no <code class="docutils literal notranslate"><span class="pre">NameError</span></code> would be raised. However, this issue can also
|
||
occur with keyword arguments using the current syntax (arguably, this syntactic
|
||
sugar could make it harder to spot). Moreover, having variables with the same
|
||
name in different scopes is broadly considered bad practice and discouraged by
|
||
linters.</p>
|
||
<p>Code editors could highlight the issue based on static analysis - <code class="docutils literal notranslate"><span class="pre">f(x=)</span></code> is
|
||
exactly equivalent to writing <code class="docutils literal notranslate"><span class="pre">f(x=x)</span></code>. If <code class="docutils literal notranslate"><span class="pre">x</span></code> does not exist, modern
|
||
editors have no problem highlighting the issue.</p>
|
||
</section>
|
||
<section id="this-syntax-increases-coupling">
|
||
<h3><a class="toc-backref" href="#this-syntax-increases-coupling" role="doc-backlink">This syntax increases coupling</a></h3>
|
||
<p>We recognise that, as ever, all syntax has the potential for misuse and so
|
||
should be applied judiciously to improve codebases. In this case, if a parameter
|
||
and its value have the same semantics in both contexts, that may suggest that
|
||
using this new syntax is appropriate and will help ameliorate the risk of
|
||
unintentional desynchronisation which harms readability.</p>
|
||
<p>However, if the two variables have different semantics, that may suggest that
|
||
this feature should not be used to encourage consistency or even that they
|
||
should be renamed.</p>
|
||
</section>
|
||
</section>
|
||
<section id="recommendations-for-using-this-syntax">
|
||
<h2><a class="toc-backref" href="#recommendations-for-using-this-syntax" role="doc-backlink">Recommendations for using this syntax</a></h2>
|
||
<p>As with any other language feature, the programmer should exercise their own
|
||
judgement about whether it is prudent to use it in any given context. We do not
|
||
recommend enforcing a rule to use the feature in all cases where it may be
|
||
applicable.</p>
|
||
<p>As described <a class="reference external" href="Thissyntaxincreasescoupling">above</a>, we propose that a
|
||
reasonable rule of thumb would be to use this in cases where a parameter and its
|
||
argument have the same semantics in order to reduce unintentional
|
||
desynchronisation without causing inappropriate coupling.</p>
|
||
</section>
|
||
<section id="impact-on-editing">
|
||
<h2><a class="toc-backref" href="#impact-on-editing" role="doc-backlink">Impact on editing</a></h2>
|
||
<section id="using-a-plain-text-editor">
|
||
<h3><a class="toc-backref" href="#using-a-plain-text-editor" role="doc-backlink">Using a plain text editor</a></h3>
|
||
<p>Editing with a plain text editor should generally be unaffected.</p>
|
||
<p>When renaming a variable using a ‘Find-Replace’ method, where this syntax is
|
||
used the developer will come across the function argument at invocation (as they
|
||
would if this syntax was not used). At that point, they can as usual decide
|
||
whether to update the argument as well or expand to the full <code class="docutils literal notranslate"><span class="pre">f(x=x)</span></code> syntax.</p>
|
||
<p>As with the current syntax, a ‘Find-Replace All’ method would fail since the
|
||
keyword argument would not exist at function definition, in the vast majority
|
||
of cases.</p>
|
||
<p>If the developer leaves the argument name unchanged and forgets to update its
|
||
value, a <code class="docutils literal notranslate"><span class="pre">NameError</span></code> will typically be raised as described
|
||
<a class="reference external" href="Renamingthevariableinthecallingcontextwillbreakthecode">above</a>.</p>
|
||
</section>
|
||
<section id="proposals-for-ides">
|
||
<h3><a class="toc-backref" href="#proposals-for-ides" role="doc-backlink">Proposals for IDEs</a></h3>
|
||
<p>In response to community feedback, we include some suggestions regarding how
|
||
IDEs could handle this syntax. However, we of course defer to the domain experts
|
||
developing IDEs to use their own discretion.</p>
|
||
<p>Most considerations are made simple by recognising that <code class="docutils literal notranslate"><span class="pre">f(x=)</span></code> is just
|
||
syntactic sugar for <code class="docutils literal notranslate"><span class="pre">f(x=x)</span></code> and should be treated the same as at present.</p>
|
||
<section id="highlighting-nameerrors">
|
||
<h4><a class="toc-backref" href="#highlighting-nameerrors" role="doc-backlink">Highlighting NameErrors</a></h4>
|
||
<p>IDEs typically offer a feature to highlight code that may cause a <code class="docutils literal notranslate"><span class="pre">NameError</span></code>.
|
||
We recommend that this syntax be treated similarly to the expanded form
|
||
<code class="docutils literal notranslate"><span class="pre">f(x=x)</span></code> to identify and highlight cases where the elided value variable may
|
||
not exist. What visual cue may be used to highlight these cases may be the same
|
||
or different from that which would be used with the current syntax, depending on
|
||
the IDE.</p>
|
||
</section>
|
||
<section id="jump-to-definition">
|
||
<h4><a class="toc-backref" href="#jump-to-definition" role="doc-backlink">Jump to definition</a></h4>
|
||
<p>There are a few possible ways that a ‘jump to definition’ feature could be
|
||
implemented depending on the caret/cursor position.</p>
|
||
<p>One option is to:</p>
|
||
<ul class="simple">
|
||
<li>Jump to the argument in the function definition if the caret/cursor is on the
|
||
argument</li>
|
||
<li>Jump to the definition of the elided variable if the caret/cursor is on the
|
||
character following the <code class="docutils literal notranslate"><span class="pre">=</span></code> in our proposed syntax</li>
|
||
</ul>
|
||
<p>Another, potentially complementary, option would be to expand the syntax
|
||
visually on mouseover and enable a <code class="docutils literal notranslate"><span class="pre">Ctrl+Click</span></code> (or <code class="docutils literal notranslate"><span class="pre">Cmd+Click</span></code>) to the
|
||
definition of the variable.</p>
|
||
</section>
|
||
<section id="highlighting-other-references">
|
||
<h4><a class="toc-backref" href="#highlighting-other-references" role="doc-backlink">Highlighting other references</a></h4>
|
||
<p>IDEs frequently highlight matching code references to the value at the current
|
||
caret/cursor position. With this shorthand syntax, when the caret/cursor is on
|
||
the argument name it may be valuable to either:</p>
|
||
<ul class="simple">
|
||
<li>Highlight both references to the argument and its value reflecting the fact
|
||
that this name now refers to both</li>
|
||
<li>Visually expand the syntax on mouseover (as above) and apply established
|
||
highlighting logic according to the cursor</li>
|
||
</ul>
|
||
</section>
|
||
<section id="rename-symbol">
|
||
<h4><a class="toc-backref" href="#rename-symbol" role="doc-backlink">Rename symbol</a></h4>
|
||
<p>There are a few ways that IDEs may wish to support a ‘Rename symbol’ feature for
|
||
this syntax. For example, if the argument is being renamed, the IDE may:</p>
|
||
<ul class="simple">
|
||
<li>Also rename the variable used as its value in each calling context where this
|
||
syntax is used</li>
|
||
<li>Expand to use the full syntax to pass the variable used as its value</li>
|
||
<li>Prompt the developer to select between the two above options</li>
|
||
</ul>
|
||
<p>The last option here seems most preferable in order to reduce unintentional
|
||
desynchronisation of names while highlighting the user to the changes.</p>
|
||
</section>
|
||
</section>
|
||
</section>
|
||
<section id="reference-implementation">
|
||
<h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2>
|
||
<p><a class="reference external" href="https://github.com/Hels15/cpython/tree/last-build">A proposed implementation</a>
|
||
for cpython has been provided by @Hels15. We will extend this implementation to
|
||
add an AST node attribute indicating for keywords whether the value was elided.</p>
|
||
</section>
|
||
<section id="references">
|
||
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
|
||
<aside class="footnote-list brackets">
|
||
<aside class="footnote brackets" id="id13" role="doc-footnote">
|
||
<dt class="label" id="id13">[1]<em> (<a href='#id1'>1</a>, <a href='#id7'>2</a>, <a href='#id10'>3</a>) </em></dt>
|
||
<dd>Short form for keyword arguments and dicts (2013)
|
||
<a class="reference external" href="https://mail.python.org/archives/list/python-ideas@python.org/thread/SQKZ273MYAY5WNIQRGEDLYTKVORVKNEZ/#LXMU22F63VPCF7CMQ4OQRH2CG6H7WCQ6">https://mail.python.org/archives/list/python-ideas@python.org/thread/SQKZ273MYAY5WNIQRGEDLYTKVORVKNEZ/#LXMU22F63VPCF7CMQ4OQRH2CG6H7WCQ6</a></aside>
|
||
<aside class="footnote brackets" id="id14" role="doc-footnote">
|
||
<dt class="label" id="id14">[2]<em> (<a href='#id2'>1</a>, <a href='#id8'>2</a>, <a href='#id11'>3</a>) </em></dt>
|
||
<dd>Keyword arguments self-assignment (2020)
|
||
<a class="reference external" href="https://mail.python.org/archives/list/python-ideas@python.org/thread/SIMIOC7OW6QKLJOTHJJVNNBDSXDE2SGV/">https://mail.python.org/archives/list/python-ideas@python.org/thread/SIMIOC7OW6QKLJOTHJJVNNBDSXDE2SGV/</a></aside>
|
||
<aside class="footnote brackets" id="id15" role="doc-footnote">
|
||
<dt class="label" id="id15">[<a href="#id3">3</a>]</dt>
|
||
<dd>Shorthand notation of dict literal and function call (2020)
|
||
<a class="reference external" href="https://discuss.python.org/t/shorthand-notation-of-dict-literal-and-function-call/5697/1">https://discuss.python.org/t/shorthand-notation-of-dict-literal-and-function-call/5697/1</a></aside>
|
||
<aside class="footnote brackets" id="id16" role="doc-footnote">
|
||
<dt class="label" id="id16">[<a href="#id4">4</a>]</dt>
|
||
<dd>Allow identifiers as keyword arguments at function call site (extension
|
||
of PEP 3102?) (2023)
|
||
<a class="reference external" href="https://discuss.python.org/t/allow-identifiers-as-keyword-arguments-at-function-call-site-extension-of-pep-3102/31677">https://discuss.python.org/t/allow-identifiers-as-keyword-arguments-at-function-call-site-extension-of-pep-3102/31677</a></aside>
|
||
<aside class="footnote brackets" id="id17" role="doc-footnote">
|
||
<dt class="label" id="id17">[<a href="#id5">5</a>]</dt>
|
||
<dd>Shorten Keyword Arguments with Implicit Notation: foo(a=a, b=b) to foo(.a, .b) (2023)
|
||
<a class="reference external" href="https://discuss.python.org/t/shorten-keyword-arguments-with-implicit-notation-foo-a-a-b-b-to-foo-a-b/33080">https://discuss.python.org/t/shorten-keyword-arguments-with-implicit-notation-foo-a-a-b-b-to-foo-a-b/33080</a></aside>
|
||
<aside class="footnote brackets" id="id18" role="doc-footnote">
|
||
<dt class="label" id="id18">[6]<em> (<a href='#id6'>1</a>, <a href='#id9'>2</a>, <a href='#id12'>3</a>) </em></dt>
|
||
<dd>Syntactic sugar to encourage use of named arguments (2023)
|
||
<a class="reference external" href="https://discuss.python.org/t/syntactic-sugar-to-encourage-use-of-named-arguments/36217">https://discuss.python.org/t/syntactic-sugar-to-encourage-use-of-named-arguments/36217</a></aside>
|
||
</aside>
|
||
</section>
|
||
<section id="copyright">
|
||
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
|
||
<p>This document is placed in the public domain or under the
|
||
CC0-1.0-Universal license, whichever is more permissive.</p>
|
||
</section>
|
||
</section>
|
||
<hr class="docutils" />
|
||
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0736.rst">https://github.com/python/peps/blob/main/peps/pep-0736.rst</a></p>
|
||
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0736.rst">2024-06-22 18:09:07 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">Motivation</a></li>
|
||
<li><a class="reference internal" href="#rationale">Rationale</a><ul>
|
||
<li><a class="reference internal" href="#encourages-use-of-named-arguments">Encourages use of named arguments</a></li>
|
||
<li><a class="reference internal" href="#reduces-verbosity">Reduces verbosity</a></li>
|
||
<li><a class="reference internal" href="#encourages-consistent-variable-names">Encourages consistent variable names</a></li>
|
||
<li><a class="reference internal" href="#highlights-arguments-not-following-this-pattern">Highlights arguments not following this pattern</a></li>
|
||
<li><a class="reference internal" href="#applicability-to-dictionary-construction">Applicability to dictionary construction</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#specification">Specification</a></li>
|
||
<li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li>
|
||
<li><a class="reference internal" href="#security-implications">Security Implications</a></li>
|
||
<li><a class="reference internal" href="#prior-art">Prior Art</a></li>
|
||
<li><a class="reference internal" href="#applicability">Applicability</a></li>
|
||
<li><a class="reference internal" href="#proposed-syntax">Proposed Syntax</a></li>
|
||
<li><a class="reference internal" href="#how-to-teach-this">How to Teach This</a></li>
|
||
<li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a><ul>
|
||
<li><a class="reference internal" href="#f-a-b-x"><code class="docutils literal notranslate"><span class="pre">f(a,</span> <span class="pre">b,</span> <span class="pre">*,</span> <span class="pre">x)</span></code></a></li>
|
||
<li><a class="reference internal" href="#f-x"><code class="docutils literal notranslate"><span class="pre">f(=x)</span></code></a></li>
|
||
<li><a class="reference internal" href="#f-x-or-f-x-or-f-x"><code class="docutils literal notranslate"><span class="pre">f(%x)</span></code> or <code class="docutils literal notranslate"><span class="pre">f(:x)</span></code> or <code class="docutils literal notranslate"><span class="pre">f(.x)</span></code></a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#objections">Objections</a><ul>
|
||
<li><a class="reference internal" href="#the-syntax-is-ugly">The syntax is ugly</a></li>
|
||
<li><a class="reference internal" href="#the-feature-is-confusing">The feature is confusing</a></li>
|
||
<li><a class="reference internal" href="#the-feature-is-not-explicit">The feature is not explicit</a></li>
|
||
<li><a class="reference internal" href="#the-feature-adds-another-way-of-doing-things">The feature adds another way of doing things</a></li>
|
||
<li><a class="reference internal" href="#renaming-the-variable-in-the-calling-context-will-break-the-code">Renaming the variable in the calling context will break the code</a></li>
|
||
<li><a class="reference internal" href="#this-syntax-increases-coupling">This syntax increases coupling</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#recommendations-for-using-this-syntax">Recommendations for using this syntax</a></li>
|
||
<li><a class="reference internal" href="#impact-on-editing">Impact on editing</a><ul>
|
||
<li><a class="reference internal" href="#using-a-plain-text-editor">Using a plain text editor</a></li>
|
||
<li><a class="reference internal" href="#proposals-for-ides">Proposals for IDEs</a><ul>
|
||
<li><a class="reference internal" href="#highlighting-nameerrors">Highlighting NameErrors</a></li>
|
||
<li><a class="reference internal" href="#jump-to-definition">Jump to definition</a></li>
|
||
<li><a class="reference internal" href="#highlighting-other-references">Highlighting other references</a></li>
|
||
<li><a class="reference internal" href="#rename-symbol">Rename symbol</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</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-0736.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> |