peps/pep-0224/index.html

356 lines
21 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 224 Attribute Docstrings | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0224/">
<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 224 Attribute Docstrings | peps.python.org'>
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0224/">
<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 224</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 224 Attribute Docstrings</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Marc-André Lemburg &lt;mal&#32;&#97;t&#32;lemburg.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">23-Aug-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.1</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#introduction">Introduction</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="#caveats-of-the-implementation">Caveats of the Implementation</a></li>
<li><a class="reference internal" href="#possible-problems">Possible Problems</a></li>
<li><a class="reference internal" href="#comments-from-our-bdfl">Comments from our BDFL</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
</details></section>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>This PEP describes the “attribute docstring” proposal for Python
2.0. This PEP tracks the status and ownership of this feature.
It contains a description of the feature and outlines changes
necessary to support the feature. The CVS revision history of
this file contains the definitive historical record.</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>This PEP proposes a small addition to the way Python currently
handles docstrings embedded in Python code.</p>
<p>Python currently only handles the case of docstrings which appear
directly after a class definition, a function definition or as
first string literal in a module. The string literals are added
to the objects in question under the <code class="docutils literal notranslate"><span class="pre">__doc__</span></code> attribute and are
from then on available for introspection tools which can extract
the contained information for help, debugging and documentation
purposes.</p>
<p>Docstrings appearing in locations other than the ones mentioned
are simply ignored and dont result in any code generation.</p>
<p>Here is an example:</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="s2">&quot;class C doc-string&quot;</span>
<span class="n">a</span> <span class="o">=</span> <span class="mi">1</span>
<span class="s2">&quot;attribute C.a doc-string (1)&quot;</span>
<span class="n">b</span> <span class="o">=</span> <span class="mi">2</span>
<span class="s2">&quot;attribute C.b doc-string (2)&quot;</span>
</pre></div>
</div>
<p>The docstrings (1) and (2) are currently being ignored by the
Python byte code compiler, but could obviously be put to good use
for documenting the named assignments that precede them.</p>
<p>This PEP proposes to also make use of these cases by proposing
semantics for adding their content to the objects in which they
appear under new generated attribute names.</p>
<p>The original idea behind this approach which also inspired the
above example was to enable inline documentation of class
attributes, which can currently only be documented in the classs
docstring or using comments which are not available for
introspection.</p>
</section>
<section id="implementation">
<h2><a class="toc-backref" href="#implementation" role="doc-backlink">Implementation</a></h2>
<p>Docstrings are handled by the byte code compiler as expressions.
The current implementation special cases the few locations
mentioned above to make use of these expressions, but otherwise
ignores the strings completely.</p>
<p>To enable use of these docstrings for documenting named
assignments (which is the natural way of defining e.g. class
attributes), the compiler will have to keep track of the last
assigned name and then use this name to assign the content of the
docstring to an attribute of the containing object by means of
storing it in as a constant which is then added to the objects
namespace during object construction time.</p>
<p>In order to preserve features like inheritance and hiding of
Pythons special attributes (ones with leading and trailing double
underscores), a special name mangling has to be applied which
uniquely identifies the docstring as belonging to the name
assignment and allows finding the docstring later on by inspecting
the namespace.</p>
<p>The following name mangling scheme achieves all of the above:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">__doc_</span><span class="o">&lt;</span><span class="n">attributename</span><span class="o">&gt;</span><span class="n">__</span>
</pre></div>
</div>
<p>To keep track of the last assigned name, the byte code compiler
stores this name in a variable of the compiling structure. This
variable defaults to NULL. When it sees a docstring, it then
checks the variable and uses the name as basis for the above name
mangling to produce an implicit assignment of the docstring to the
mangled name. It then resets the variable to NULL to avoid
duplicate assignments.</p>
<p>If the variable does not point to a name (i.e. is NULL), no
assignments are made. These will continue to be ignored like
before. All classical docstrings fall under this case, so no
duplicate assignments are done.</p>
<p>In the above example this would result in the following new class
attributes to be created:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">C</span><span class="o">.</span><span class="n">__doc_a__</span> <span class="o">==</span> <span class="s2">&quot;attribute C.a doc-string (1)&quot;</span>
<span class="n">C</span><span class="o">.</span><span class="n">__doc_b__</span> <span class="o">==</span> <span class="s2">&quot;attribute C.b doc-string (2)&quot;</span>
</pre></div>
</div>
<p>A patch to the current CVS version of Python 2.0 which implements
the above is available on SourceForge at <a class="footnote-reference brackets" href="#id2" id="id1">[1]</a>.</p>
</section>
<section id="caveats-of-the-implementation">
<h2><a class="toc-backref" href="#caveats-of-the-implementation" role="doc-backlink">Caveats of the Implementation</a></h2>
<p>Since the implementation does not reset the compiling structure
variable when processing a non-expression, e.g. a function
definition, the last assigned name remains active until either the
next assignment or the next occurrence of a docstring.</p>
<p>This can lead to cases where the docstring and assignment may be
separated by other expressions:</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="s2">&quot;C doc string&quot;</span>
<span class="n">b</span> <span class="o">=</span> <span class="mi">2</span>
<span class="k">def</span> <span class="nf">x</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="s2">&quot;C.x doc string&quot;</span>
<span class="n">y</span> <span class="o">=</span> <span class="mi">3</span>
<span class="k">return</span> <span class="mi">1</span>
<span class="s2">&quot;b&#39;s doc string&quot;</span>
</pre></div>
</div>
<p>Since the definition of method “x” currently does not reset the
used assignment name variable, it is still valid when the compiler
reaches the docstring “bs doc string” and thus assigns the string
to <code class="docutils literal notranslate"><span class="pre">__doc_b__</span></code>.</p>
<p>A possible solution to this problem would be resetting the name
variable for all non-expression nodes in the compiler.</p>
</section>
<section id="possible-problems">
<h2><a class="toc-backref" href="#possible-problems" role="doc-backlink">Possible Problems</a></h2>
<p>Even though highly unlikely, attribute docstrings could get
accidentally concatenated to the attributes value:</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">x</span> <span class="o">=</span> <span class="s2">&quot;text&quot;</span> \
<span class="s2">&quot;x&#39;s docstring&quot;</span>
</pre></div>
</div>
<p>The trailing slash would cause the Python compiler to concatenate
the attribute value and the docstring.</p>
<p>A modern syntax highlighting editor would easily make this
accident visible, though, and by simply inserting empty lines
between the attribute definition and the docstring you can avoid
the possible concatenation completely, so the problem is
negligible.</p>
<p>Another possible problem is that of using triple quoted strings as
a way to uncomment parts of your code.</p>
<p>If there happens to be an assignment just before the start of the
comment string, then the compiler will treat the comment as
docstring attribute and apply the above logic to it.</p>
<p>Besides generating a docstring for an otherwise undocumented
attribute there is no breakage.</p>
</section>
<section id="comments-from-our-bdfl">
<h2><a class="toc-backref" href="#comments-from-our-bdfl" role="doc-backlink">Comments from our BDFL</a></h2>
<p>Early comments on the PEP from Guido:</p>
<blockquote>
<div>I “kinda” like the idea of having attribute docstrings (meaning
its not of great importance to me) but there are two things I
dont like in your current proposal:<ol class="arabic simple">
<li>The syntax you propose is too ambiguous: as you say,
stand-alone string literal are used for other purposes and could
suddenly become attribute docstrings.</li>
<li>I dont like the access method either (<code class="docutils literal notranslate"><span class="pre">__doc_&lt;attrname&gt;__</span></code>).</li>
</ol>
</div></blockquote>
<p>The authors reply:</p>
<blockquote>
<div><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="mf">1.</span> <span class="n">The</span> <span class="n">syntax</span> <span class="n">you</span> <span class="n">propose</span> <span class="ow">is</span> <span class="n">too</span> <span class="n">ambiguous</span><span class="p">:</span> <span class="k">as</span> <span class="n">you</span> <span class="n">say</span><span class="p">,</span> <span class="n">stand</span><span class="o">-</span><span class="n">alone</span>
<span class="o">&gt;</span> <span class="n">string</span> <span class="n">literal</span> <span class="n">are</span> <span class="n">used</span> <span class="k">for</span> <span class="n">other</span> <span class="n">purposes</span> <span class="ow">and</span> <span class="n">could</span> <span class="n">suddenly</span>
<span class="o">&gt;</span> <span class="n">become</span> <span class="n">attribute</span> <span class="n">docstrings</span><span class="o">.</span>
</pre></div>
</div>
<p>This can be fixed by introducing some extra checks in the
compiler to reset the “doc attribute” flag in the compiler
struct.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="mf">2.</span> <span class="n">I</span> <span class="n">don</span><span class="s1">&#39;t like the access method either (``__doc_&lt;attrname&gt;__``).</span>
</pre></div>
</div>
<p>Any other name will do. It will only have to match these
criteria:</p>
<ul class="simple">
<li>must start with two underscores (to match <code class="docutils literal notranslate"><span class="pre">__doc__</span></code>)</li>
<li>must be extractable using some form of inspection (e.g. by using
a naming convention which includes some fixed name part)</li>
<li>must be compatible with class inheritance (i.e. should be
stored as attribute)</li>
</ul>
</div></blockquote>
<p>Later on in March, Guido pronounced on this PEP in March 2001 (on
python-dev). Here are his reasons for rejection mentioned in
private mail to the author of this PEP:</p>
<blockquote>
<div><p>It might be useful, but I really hate the proposed syntax.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="o">=</span> <span class="mi">1</span>
<span class="s2">&quot;foo bar&quot;</span>
<span class="n">b</span> <span class="o">=</span> <span class="mi">1</span>
</pre></div>
</div>
<p>I really have no way to know whether “foo bar” is a docstring
for a or for b.</p>
<p></p>
<p>You can use this convention:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">__doc_a__</span> <span class="o">=</span> <span class="s2">&quot;doc string for a&quot;</span>
</pre></div>
</div>
<p>This makes it available at runtime.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; Are you completely opposed to adding attribute documentation
&gt; to Python or is it just the way the implementation works ? I
&gt; find the syntax proposed in the PEP very intuitive and many
&gt; other users on c.l.p and in private emails have supported it
&gt; at the time I wrote the PEP.
</pre></div>
</div>
<p>Its not the implementation, its the syntax. It doesnt
convey a clear enough coupling between the variable and the
doc string.</p>
</div></blockquote>
</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 id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id2" role="doc-footnote">
<dt class="label" id="id2">[<a href="#id1">1</a>]</dt>
<dd><a class="reference external" href="http://sourceforge.net/patch/?func=detailpatch&amp;patch_id=101264&amp;group_id=5470">http://sourceforge.net/patch/?func=detailpatch&amp;patch_id=101264&amp;group_id=5470</a></aside>
</aside>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0224.rst">https://github.com/python/peps/blob/main/peps/pep-0224.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0224.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="#introduction">Introduction</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="#caveats-of-the-implementation">Caveats of the Implementation</a></li>
<li><a class="reference internal" href="#possible-problems">Possible Problems</a></li>
<li><a class="reference internal" href="#comments-from-our-bdfl">Comments from our BDFL</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0224.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>