CINXE.COM
PEP 542 – Dot Notation Assignment In Function Header | peps.python.org
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="color-scheme" content="light dark"> <title>PEP 542 – Dot Notation Assignment In Function Header | peps.python.org</title> <link rel="shortcut icon" href="../_static/py.png"> <link rel="canonical" href="https://peps.python.org/pep-0542/"> <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 542 – Dot Notation Assignment In Function Header | peps.python.org'> <meta property="og:description" content="Function definitions only allow simple function names to be used, even though functions are assignable first class objects."> <meta property="og:type" content="website"> <meta property="og:url" content="https://peps.python.org/pep-0542/"> <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="Function definitions only allow simple function names to be used, even though functions are assignable first class objects."> <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 542</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 542 – Dot Notation Assignment In Function Header</h1> <dl class="rfc2822 field-list simple"> <dt class="field-odd">Author<span class="colon">:</span></dt> <dd class="field-odd">Markus Meskanen <markusmeskanen at gmail.com></dd> <dt class="field-even">Status<span class="colon">:</span></dt> <dd class="field-even"><abbr title="Formally declined and will not be accepted">Rejected</abbr></dd> <dt class="field-odd">Type<span class="colon">:</span></dt> <dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd> <dt class="field-even">Created<span class="colon">:</span></dt> <dd class="field-even">10-Feb-2017</dd> <dt class="field-odd">Resolution<span class="colon">:</span></dt> <dd class="field-odd"><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2019-March/156695.html">Python-Dev message</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="#rationale">Rationale</a></li> <li><a class="reference internal" href="#implementation">Implementation</a></li> <li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</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>Function definitions only allow simple function names to be used, even though functions are assignable first class objects.</p> <p>This PEP proposes adding support for assigning a function to a class or instance attribute directly in the function definition’s header by using the dot notation to separate the object from the function’s name.</p> <p>Although a similar feature, this PEP does not address general assignment to anything that supports assignment, such as dict keys and list indexes.</p> </section> <section id="rationale"> <h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2> <p>Currently if a function needs to be assigned to a class or instance attribute, it requires an additional assignment statement to be made:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">MyClass</span><span class="p">:</span> <span class="o">...</span> <span class="n">my_instance</span> <span class="o">=</span> <span class="n">MyClass</span><span class="p">()</span> <span class="k">def</span> <span class="nf">my_function</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="o">...</span> <span class="c1"># Assign to class attribute</span> <span class="n">MyClass</span><span class="o">.</span><span class="n">my_function</span> <span class="o">=</span> <span class="n">my_function</span> <span class="c1"># Or assign to instance attribute</span> <span class="n">my_instance</span><span class="o">.</span><span class="n">my_function</span> <span class="o">=</span> <span class="n">my_function</span> </pre></div> </div> <p>While this isn’t usually an inconvenience, using dot notation to assign directly in the function’s header would greatly simplify this:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">MyClass</span><span class="p">:</span> <span class="o">...</span> <span class="n">my_instance</span> <span class="o">=</span> <span class="n">MyClass</span><span class="p">()</span> <span class="c1"># Assign to class attribute</span> <span class="k">def</span> <span class="nf">MyClass</span><span class="o">.</span><span class="n">my_function</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="o">...</span> <span class="c1"># Or assign to instance attribute</span> <span class="k">def</span> <span class="nf">my_instance</span><span class="o">.</span><span class="n">my_function</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="o">...</span> </pre></div> </div> <p>There are multiple reasons to use this functionality over a standard class method, for example when the class is referenced inside the function’s header (such as with decorators and typing). This is also useful when an instance requires a callback attribute:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Menu</span><span class="p">:</span> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">items</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">select_callback</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">items</span> <span class="o">=</span> <span class="n">items</span> <span class="k">if</span> <span class="n">items</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="k">else</span> <span class="p">[]</span> <span class="bp">self</span><span class="o">.</span><span class="n">select_callback</span> <span class="o">=</span> <span class="n">select_callback</span> <span class="n">my_menu</span> <span class="o">=</span> <span class="n">Menu</span><span class="p">([</span><span class="n">item1</span><span class="p">,</span> <span class="n">item2</span><span class="p">])</span> <span class="k">def</span> <span class="nf">my_menu</span><span class="o">.</span><span class="n">select_callback</span><span class="p">(</span><span class="n">item_index</span><span class="p">,</span> <span class="n">menu</span><span class="p">):</span> <span class="nb">print</span><span class="p">(</span><span class="n">menu</span><span class="o">.</span><span class="n">items</span><span class="p">[</span><span class="n">item_index</span><span class="p">])</span> </pre></div> </div> <p>As opposed to:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">my_menu</span> <span class="o">=</span> <span class="n">Menu</span><span class="p">([</span><span class="n">item1</span><span class="p">,</span> <span class="n">item2</span><span class="p">])</span> <span class="k">def</span> <span class="nf">select_callback</span><span class="p">(</span><span class="n">item_index</span><span class="p">,</span> <span class="n">menu</span><span class="p">):</span> <span class="nb">print</span><span class="p">(</span><span class="n">menu</span><span class="o">.</span><span class="n">items</span><span class="p">[</span><span class="n">item_index</span><span class="p">])</span> <span class="n">my_menu</span><span class="o">.</span><span class="n">select_callback</span> <span class="o">=</span> <span class="n">select_callback</span> </pre></div> </div> <p>Or defining them in an “unnatural” order:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">select_callback</span><span class="p">(</span><span class="n">item_index</span><span class="p">,</span> <span class="n">menu</span><span class="p">):</span> <span class="nb">print</span><span class="p">(</span><span class="n">menu</span><span class="o">.</span><span class="n">items</span><span class="p">[</span><span class="n">item_index</span><span class="p">])</span> <span class="n">my_menu</span> <span class="o">=</span> <span class="n">Menu</span><span class="p">([</span><span class="n">item1</span><span class="p">,</span> <span class="n">item2</span><span class="p">],</span> <span class="n">select_callback</span><span class="p">)</span> </pre></div> </div> <p>It reads better than the “unnatural” way, since you already know at the time of the function definition what it’s goig to be used for. It also saves one line of code while removing visual complexity.</p> <p>The feature would also avoid leaving the function’s name into the global namespace:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">eggs</span> <span class="o">=</span> <span class="s1">'something'</span> <span class="k">def</span> <span class="nf">Spam</span><span class="o">.</span><span class="n">eggs</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="o">...</span> <span class="k">def</span> <span class="nf">Cheese</span><span class="o">.</span><span class="n">eggs</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="o">...</span> <span class="k">assert</span> <span class="n">eggs</span> <span class="o">==</span> <span class="s1">'something'</span> </pre></div> </div> <p>Ideally this would be just syntastic sugar:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">x</span><span class="o">.</span><span class="n">y</span><span class="p">():</span> <span class="o">...</span> <span class="c1"># Equals to</span> <span class="k">def</span> <span class="nf">y</span><span class="p">():</span> <span class="o">...</span> <span class="n">x</span><span class="o">.</span><span class="n">y</span> <span class="o">=</span> <span class="n">y</span> </pre></div> </div> <p>Similar to how decorators are syntastic sugar:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@decorate</span> <span class="k">def</span> <span class="nf">f</span><span class="p">():</span> <span class="o">...</span> <span class="c1"># Equals to</span> <span class="k">def</span> <span class="nf">f</span><span class="p">():</span> <span class="o">...</span> <span class="n">f</span> <span class="o">=</span> <span class="n">decorate</span><span class="p">(</span><span class="n">f</span><span class="p">)</span> </pre></div> </div> </section> <section id="implementation"> <h2><a class="toc-backref" href="#implementation" role="doc-backlink">Implementation</a></h2> <p>The <code class="docutils literal notranslate"><span class="pre">__name__</span></code> would follow the principles of a normal function:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">MyClass</span><span class="p">:</span> <span class="k">def</span> <span class="nf">my_function1</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="o">...</span> <span class="k">def</span> <span class="nf">MyClass</span><span class="o">.</span><span class="n">my_function2</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="o">...</span> <span class="k">assert</span> <span class="n">my_function1</span><span class="o">.</span><span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'my_function1'</span> <span class="k">assert</span> <span class="n">my_function2</span><span class="o">.</span><span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'my_function2'</span> </pre></div> </div> <p>The grammar would use <code class="docutils literal notranslate"><span class="pre">dotted_name</span></code> to support chaining of attributes:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">Person</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">fset</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">_name</span> <span class="o">=</span> <span class="n">value</span> </pre></div> </div> </section> <section id="backwards-compatibility"> <h2><a class="toc-backref" href="#backwards-compatibility" role="doc-backlink">Backwards Compatibility</a></h2> <p>This PEP is fully backwards compatible.</p> </section> <section id="copyright"> <h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2> <p>This document has been placed in the public domain.</p> </section> </section> <hr class="docutils" /> <p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0542.rst">https://github.com/python/peps/blob/main/peps/pep-0542.rst</a></p> <p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0542.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="#rationale">Rationale</a></li> <li><a class="reference internal" href="#implementation">Implementation</a></li> <li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</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-0542.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>