peps/pep-3130/index.html

330 lines
25 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!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: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="Python Enhancement Proposals (PEPs)">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 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 arent 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 modules 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 objects 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>