CINXE.COM

PEP 3130 – Access to Current Module/Class/Function | 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 3130 – Access to Current Module/Class/Function | peps.python.org</title> <link rel="shortcut icon" href="../_static/py.png"> <link rel="canonical" href="https://peps.python.org/pep-3130/"> <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 3130 – Access to Current Module/Class/Function | peps.python.org'> <meta property="og:description" content="It is common to need a reference to the current module, class, or function, but there is currently no entirely correct way to do this. This PEP proposes adding the keywords __module__, __class__, and __function__."> <meta property="og:type" content="website"> <meta property="og:url" content="https://peps.python.org/pep-3130/"> <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="It is common to need a reference to the current module, class, or function, but there is currently no entirely correct way to do this. This PEP proposes adding the keywords __module__, __class__, and __function__."> <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 3130</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 3130 – Access to Current Module/Class/Function</h1> <dl class="rfc2822 field-list simple"> <dt class="field-odd">Author<span class="colon">:</span></dt> <dd class="field-odd">Jim J. Jewett &lt;jimjjewett&#32;&#97;t&#32;gmail.com&gt;</dd> <dt class="field-even">Status<span class="colon">:</span></dt> <dd class="field-even"><abbr title="Formally declined and will not be accepted">Rejected</abbr></dd> <dt class="field-odd">Type<span class="colon">:</span></dt> <dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd> <dt class="field-even">Created<span class="colon">:</span></dt> <dd class="field-even">22-Apr-2007</dd> <dt class="field-odd">Python-Version<span class="colon">:</span></dt> <dd class="field-odd">3.0</dd> <dt class="field-even">Post-History<span class="colon">:</span></dt> <dd class="field-even">22-Apr-2007</dd> </dl> <hr class="docutils" /> <section id="contents"> <details><summary>Table of Contents</summary><ul class="simple"> <li><a class="reference internal" href="#rejection-notice">Rejection Notice</a></li> <li><a class="reference internal" href="#abstract">Abstract</a></li> <li><a class="reference internal" href="#rationale-for-module">Rationale for <code class="docutils literal notranslate"><span class="pre">__module__</span></code></a></li> <li><a class="reference internal" href="#rationale-for-class">Rationale for <code class="docutils literal notranslate"><span class="pre">__class__</span></code></a></li> <li><a class="reference internal" href="#rationale-for-function">Rationale for <code class="docutils literal notranslate"><span class="pre">__function__</span></code></a></li> <li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li> <li><a class="reference internal" href="#implementation">Implementation</a></li> <li><a class="reference internal" href="#open-issues">Open Issues</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="rejection-notice"> <h2><a class="toc-backref" href="#rejection-notice" role="doc-backlink">Rejection Notice</a></h2> <p>This PEP is rejected. It is not clear how it should be implemented or what the precise semantics should be in edge cases, and there aren’t enough important use cases given. response has been lukewarm at best.</p> </section> <section id="abstract"> <h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2> <p>It is common to need a reference to the current module, class, or function, but there is currently no entirely correct way to do this. This PEP proposes adding the keywords <code class="docutils literal notranslate"><span class="pre">__module__</span></code>, <code class="docutils literal notranslate"><span class="pre">__class__</span></code>, and <code class="docutils literal notranslate"><span class="pre">__function__</span></code>.</p> </section> <section id="rationale-for-module"> <h2><a class="toc-backref" href="#rationale-for-module" role="doc-backlink">Rationale for <code class="docutils literal notranslate"><span class="pre">__module__</span></code></a></h2> <p>Many modules export various functions, classes, and other objects, but will perform additional activities (such as running unit tests) when run as a script. The current idiom is to test whether the module’s name has been set to magic value.</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span> <span class="o">...</span> </pre></div> </div> <p>More complicated introspection requires a module to (attempt to) import itself. If importing the expected name actually produces a different module, there is no good workaround.</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># __import__ lets you use a variable, but... it gets more</span> <span class="c1"># complicated if the module is in a package.</span> <span class="nb">__import__</span><span class="p">(</span><span class="vm">__name__</span><span class="p">)</span> <span class="c1"># So just go to sys modules... and hope that the module wasn&#39;t</span> <span class="c1"># hidden/removed (perhaps for security), that __name__ wasn&#39;t</span> <span class="c1"># changed, and definitely hope that no other module with the</span> <span class="c1"># same name is now available.</span> <span class="k">class</span> <span class="nc">X</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="k">pass</span> <span class="kn">import</span> <span class="nn">sys</span> <span class="n">mod</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="p">[</span><span class="vm">__name__</span><span class="p">]</span> <span class="n">mod</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="p">[</span><span class="n">X</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__module__</span><span class="p">]</span> </pre></div> </div> <p>Proposal: Add a <code class="docutils literal notranslate"><span class="pre">__module__</span></code> keyword which refers to the module currently being defined (executed). (But see open issues.)</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># XXX sys.main is still changing as draft progresses. May</span> <span class="c1"># really need sys.modules[sys.main]</span> <span class="k">if</span> <span class="vm">__module__</span> <span class="ow">is</span> <span class="n">sys</span><span class="o">.</span><span class="n">main</span><span class="p">:</span> <span class="c1"># assumes PEP (3122), Cannon</span> <span class="o">...</span> </pre></div> </div> </section> <section id="rationale-for-class"> <h2><a class="toc-backref" href="#rationale-for-class" role="doc-backlink">Rationale for <code class="docutils literal notranslate"><span class="pre">__class__</span></code></a></h2> <p>Class methods are passed the current instance; from this they can determine <code class="docutils literal notranslate"><span class="pre">self.__class__</span></code> (or cls, for class methods). Unfortunately, this reference is to the object’s actual class, which may be a subclass of the defining class. The current workaround is to repeat the name of the class, and assume that the name will not be rebound.</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">C</span><span class="p">(</span><span class="n">B</span><span class="p">):</span> <span class="k">def</span> <span class="nf">meth</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="nb">super</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">meth</span><span class="p">()</span> <span class="c1"># Hope C is never rebound.</span> <span class="k">class</span> <span class="nc">D</span><span class="p">(</span><span class="n">C</span><span class="p">):</span> <span class="k">def</span> <span class="nf">meth</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="c1"># ?!? issubclass(D,C), so it &quot;works&quot;:</span> <span class="nb">super</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">meth</span><span class="p">()</span> </pre></div> </div> <p>Proposal: Add a <code class="docutils literal notranslate"><span class="pre">__class__</span></code> keyword which refers to the class currently being defined (executed). (But see open issues.)</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">C</span><span class="p">(</span><span class="n">B</span><span class="p">):</span> <span class="k">def</span> <span class="nf">meth</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="nb">super</span><span class="p">(</span><span class="vm">__class__</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">meth</span><span class="p">()</span> </pre></div> </div> <p>Note that super calls may be further simplified by the “New Super” PEP (Spealman). The <code class="docutils literal notranslate"><span class="pre">__class__</span></code> (or <code class="docutils literal notranslate"><span class="pre">__this_class__</span></code>) attribute came up in attempts to simplify the explanation and/or implementation of that PEP, but was separated out as an independent decision.</p> <p>Note that <code class="docutils literal notranslate"><span class="pre">__class__</span></code> (or <code class="docutils literal notranslate"><span class="pre">__this_class__</span></code>) is not quite the same as the <code class="docutils literal notranslate"><span class="pre">__thisclass__</span></code> property on bound super objects. The existing <code class="docutils literal notranslate"><span class="pre">super.__thisclass__</span></code> property refers to the class from which the Method Resolution Order search begins. In the above class D, it would refer to (the current reference of name) C.</p> </section> <section id="rationale-for-function"> <h2><a class="toc-backref" href="#rationale-for-function" role="doc-backlink">Rationale for <code class="docutils literal notranslate"><span class="pre">__function__</span></code></a></h2> <p>Functions (including methods) often want access to themselves, usually for a private storage location or true recursion. While there are several workarounds, all have their drawbacks.</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">counter</span><span class="p">(</span><span class="n">_total</span><span class="o">=</span><span class="p">[</span><span class="mi">0</span><span class="p">]):</span> <span class="c1"># _total shouldn&#39;t really appear in the</span> <span class="c1"># signature at all; the list wrapping and</span> <span class="c1"># [0] unwrapping obscure the code</span> <span class="n">_total</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">return</span> <span class="n">_total</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="nd">@annotate</span><span class="p">(</span><span class="n">total</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span> <span class="k">def</span> <span class="nf">counter</span><span class="p">():</span> <span class="c1"># Assume name counter is never rebound:</span> <span class="n">counter</span><span class="o">.</span><span class="n">total</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">return</span> <span class="n">counter</span><span class="o">.</span><span class="n">total</span> <span class="c1"># class exists only to provide storage:</span> <span class="k">class</span> <span class="nc">_wrap</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="n">__total</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">__total</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">__total</span> <span class="c1"># set module attribute to a bound method:</span> <span class="n">accum</span> <span class="o">=</span> <span class="n">_wrap</span><span class="p">()</span><span class="o">.</span><span class="n">f</span> <span class="c1"># This function calls &quot;factorial&quot;, which should be itself --</span> <span class="c1"># but the same programming styles that use heavy recursion</span> <span class="c1"># often have a greater willingness to rebind function names.</span> <span class="k">def</span> <span class="nf">factorial</span><span class="p">(</span><span class="n">n</span><span class="p">):</span> <span class="k">return</span> <span class="p">(</span><span class="n">n</span> <span class="o">*</span> <span class="n">factorial</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="k">if</span> <span class="n">n</span> <span class="k">else</span> <span class="mi">1</span><span class="p">)</span> </pre></div> </div> <p>Proposal: Add a <code class="docutils literal notranslate"><span class="pre">__function__</span></code> keyword which refers to the function (or method) currently being defined (executed). (But see open issues.)</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@annotate</span><span class="p">(</span><span class="n">total</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span> <span class="k">def</span> <span class="nf">counter</span><span class="p">():</span> <span class="c1"># Always refers to this function obj:</span> <span class="n">__function__</span><span class="o">.</span><span class="n">total</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">return</span> <span class="n">__function__</span><span class="o">.</span><span class="n">total</span> <span class="k">def</span> <span class="nf">factorial</span><span class="p">(</span><span class="n">n</span><span class="p">):</span> <span class="k">return</span> <span class="p">(</span><span class="n">n</span> <span class="o">*</span> <span class="n">__function__</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="k">if</span> <span class="n">n</span> <span class="k">else</span> <span class="mi">1</span><span class="p">)</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>While a user could be using these names already, double-underscore names ( <code class="docutils literal notranslate"><span class="pre">__anything__</span></code> ) are explicitly reserved to the interpreter. It is therefore acceptable to introduce special meaning to these names within a single feature release.</p> </section> <section id="implementation"> <h2><a class="toc-backref" href="#implementation" role="doc-backlink">Implementation</a></h2> <p>Ideally, these names would be keywords treated specially by the bytecode compiler.</p> <p>Guido has suggested <a class="footnote-reference brackets" href="#id3" id="id1">[1]</a> using a cell variable filled in by the metaclass.</p> <p>Michele Simionato has provided a prototype using bytecode hacks <a class="footnote-reference brackets" href="#id4" id="id2">[2]</a>. This does not require any new bytecode operators; it just modifies the which specific sequence of existing operators gets run.</p> </section> <section id="open-issues"> <h2><a class="toc-backref" href="#open-issues" role="doc-backlink">Open Issues</a></h2> <ul class="simple"> <li>Are <code class="docutils literal notranslate"><span class="pre">__module__</span></code>, <code class="docutils literal notranslate"><span class="pre">__class__</span></code>, and <code class="docutils literal notranslate"><span class="pre">__function__</span></code> the right names? In particular, should the names include the word “this”, either as <code class="docutils literal notranslate"><span class="pre">__this_module__</span></code>, <code class="docutils literal notranslate"><span class="pre">__this_class__</span></code>, and <code class="docutils literal notranslate"><span class="pre">__this_function__</span></code>, (format discussed on the python-3000 and python-ideas lists) or as <code class="docutils literal notranslate"><span class="pre">__thismodule__</span></code>, <code class="docutils literal notranslate"><span class="pre">__thisclass__</span></code>, and <code class="docutils literal notranslate"><span class="pre">__thisfunction__</span></code> (inspired by, but conflicting with, current usage of super.``__thisclass__``).</li> <li>Are all three keywords needed, or should this enhancement be limited to a subset of the objects? Should methods be treated separately from other functions?</li> </ul> </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="id3" role="doc-footnote"> <dt class="label" id="id3">[<a href="#id1">1</a>]</dt> <dd>Fixing super anyone? Guido van Rossum <a class="reference external" href="https://mail.python.org/pipermail/python-3000/2007-April/006671.html">https://mail.python.org/pipermail/python-3000/2007-April/006671.html</a></aside> <aside class="footnote brackets" id="id4" role="doc-footnote"> <dt class="label" id="id4">[<a href="#id2">2</a>]</dt> <dd>Descriptor/Decorator challenge, Michele Simionato <a class="reference external" href="http://groups.google.com/group/comp.lang.python/browse_frm/thread/a6010c7494871bb1/62a2da68961caeb6?lnk=gst&amp;q=simionato+challenge&amp;rnum=1&amp;hl=en#62a2da68961caeb6">http://groups.google.com/group/comp.lang.python/browse_frm/thread/a6010c7494871bb1/62a2da68961caeb6?lnk=gst&amp;q=simionato+challenge&amp;rnum=1&amp;hl=en#62a2da68961caeb6</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-3130.rst">https://github.com/python/peps/blob/main/peps/pep-3130.rst</a></p> <p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-3130.rst">2023-09-09 17:39:29 GMT</a></p> </article> <nav id="pep-sidebar"> <h2>Contents</h2> <ul> <li><a class="reference internal" href="#rejection-notice">Rejection Notice</a></li> <li><a class="reference internal" href="#abstract">Abstract</a></li> <li><a class="reference internal" href="#rationale-for-module">Rationale for <code class="docutils literal notranslate"><span class="pre">__module__</span></code></a></li> <li><a class="reference internal" href="#rationale-for-class">Rationale for <code class="docutils literal notranslate"><span class="pre">__class__</span></code></a></li> <li><a class="reference internal" href="#rationale-for-function">Rationale for <code class="docutils literal notranslate"><span class="pre">__function__</span></code></a></li> <li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li> <li><a class="reference internal" href="#implementation">Implementation</a></li> <li><a class="reference internal" href="#open-issues">Open Issues</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-3130.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>

Pages: 1 2 3 4 5 6 7 8 9 10