peps/pep-3117/index.html

377 lines
23 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 3117 Postfix type declarations | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-3117/">
<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 3117 Postfix type declarations | peps.python.org'>
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-3117/">
<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 3117</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 3117 Postfix type declarations</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Georg Brandl &lt;georg&#32;&#97;t&#32;python.org&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">01-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"><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="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#specification">Specification</a></li>
<li><a class="reference internal" href="#unicode-replacement-units">Unicode replacement units</a></li>
<li><a class="reference internal" href="#the-typedef-statement">The <code class="docutils literal notranslate"><span class="pre">typedef</span></code> statement</a></li>
<li><a class="reference internal" href="#example">Example</a></li>
<li><a class="reference internal" href="#compatibility-issues">Compatibility issues</a></li>
<li><a class="reference internal" href="#rejection">Rejection</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#acknowledgements">Acknowledgements</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 the addition of a postfix type declaration syntax to
Python. It also specifies a new <code class="docutils literal notranslate"><span class="pre">typedef</span></code> statement which is used to create
new mappings between types and declarators.</p>
<p>Its acceptance will greatly enhance the Python user experience as well as
eliminate one of the warts that deter users of other programming languages from
switching to Python.</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>Python has long suffered from the lack of explicit type declarations. Being one
of the few aspects in which the language deviates from its Zen, this wart has
sparked many a discussion between Python heretics and members of the PSU (for
a few examples, see <a class="reference internal" href="#ex1" id="id1"><span>[EX1]</span></a>, <a class="reference internal" href="#ex2" id="id2"><span>[EX2]</span></a> or <a class="reference internal" href="#ex3" id="id3"><span>[EX3]</span></a>), and it also made it a large-scale
enterprise success unlikely.</p>
<p>However, if one wants to put an end to this misery, a decent Pythonic syntax
must be found. In almost all languages that have them, type declarations lack
this quality: they are verbose, often needing <em>multiple words</em> for a single
type, or they are hard to comprehend (e.g., a certain language uses completely
unrelated <a class="footnote-reference brackets" href="#id8" id="id4">[1]</a> adjectives like <code class="docutils literal notranslate"><span class="pre">dim</span></code> for type declaration).</p>
<p>Therefore, this PEP combines the move to type declarations with another bold
move that will once again prove that Python is not only future-proof but
future-embracing: the introduction of Unicode characters as an integral
constituent of source code.</p>
<p>Unicode makes it possible to express much more with much less characters, which
is in accordance with the <a class="pep reference internal" href="../pep-0020/" title="PEP 20 The Zen of Python">Zen</a> (“Readability counts.”). Additionally, it
eliminates the need for a separate type declaration statement, and last but not
least, it makes Python measure up to Perl 6, which already uses Unicode for its
operators. <a class="footnote-reference brackets" href="#id9" id="id5">[2]</a></p>
</section>
<section id="specification">
<h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2>
<p>When the type declaration mode is in operation, the grammar is changed so that
each <code class="docutils literal notranslate"><span class="pre">NAME</span></code> must consist of two parts: a name and a type declarator, which is
exactly one Unicode character.</p>
<p>The declarator uniquely specifies the type of the name, and if it occurs on the
left hand side of an expression, this type is enforced: an <code class="docutils literal notranslate"><span class="pre">InquisitionError</span></code>
exception is raised if the returned type doesnt match the declared type. <a class="footnote-reference brackets" href="#id10" id="id6">[3]</a></p>
<p>Also, function call result types have to be specified. If the result of the call
does not have the declared type, an <code class="docutils literal notranslate"><span class="pre">InquisitionError</span></code> is raised. Caution: the
declarator for the result should not be confused with the declarator for the
function object (see the example below).</p>
<p>Type declarators after names that are only read, not assigned to, are not strictly
necessary but enforced anyway (see the Python Zen: “Explicit is better than
implicit.”).</p>
<p>The mapping between types and declarators is not static. It can be completely
customized by the programmer, but for convenience there are some predefined
mappings for some built-in types:</p>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head">Type</th>
<th class="head">Declarator</th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">object</span></code></td>
<td><EFBFBD> (REPLACEMENT CHARACTER)</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">int</span></code></td>
<td> (DOUBLE-STRUCK CAPITAL N)</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">float</span></code></td>
<td> (ESTIMATED SYMBOL)</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td>✓ (CHECK MARK)</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">complex</span></code></td>
<td> (DOUBLE-STRUCK CAPITAL C)</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">str</span></code></td>
<td>✎ (LOWER RIGHT PENCIL)</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">unicode</span></code></td>
<td>✒ (BLACK NIB)</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">tuple</span></code></td>
<td>⒯ (PARENTHESIZED LATIN SMALL LETTER T)</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">list</span></code></td>
<td>♨ (HOT SPRINGS)</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">dict</span></code></td>
<td>⧟ (DOUBLE-ENDED MULTIMAP)</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">set</span></code></td>
<td>∅ (EMPTY SET) (<em>Note:</em> this is also for full sets)</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">frozenset</span></code></td>
<td>☃ (SNOWMAN)</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">datetime</span></code></td>
<td>⌚ (WATCH)</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">function</span></code></td>
<td>ƛ (LATIN SMALL LETTER LAMBDA WITH STROKE)</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">generator</span></code></td>
<td>⚛ (ATOM SYMBOL)</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">Exception</span></code></td>
<td>⌁ (ELECTRIC ARROW)</td>
</tr>
</tbody>
</table>
<p>The declarator for the <code class="docutils literal notranslate"><span class="pre">None</span></code> type is a zero-width space.</p>
<p>These characters should be obvious and easy to remember and type for every
programmer.</p>
</section>
<section id="unicode-replacement-units">
<h2><a class="toc-backref" href="#unicode-replacement-units" role="doc-backlink">Unicode replacement units</a></h2>
<p>Since even in our modern, globalized world there are still some old-fashioned
rebels who cant or dont want to use Unicode in their source code, and since
Python is a forgiving language, a fallback is provided for those:</p>
<p>Instead of the single Unicode character, they can type <code class="docutils literal notranslate"><span class="pre">name${UNICODE</span> <span class="pre">NAME</span> <span class="pre">OF</span>
<span class="pre">THE</span> <span class="pre">DECLARATOR}$</span></code>. For example, these two function definitions are equivalent:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">fooƛ</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
<span class="k">return</span> <span class="kc">None</span>
</pre></div>
</div>
<p>and</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>def foo${LATIN SMALL LETTER LAMBDA WITH STROKE}$(x${DOUBLE-STRUCK CAPITAL C}$):
return None${ZERO WIDTH NO-BREAK SPACE}$
</pre></div>
</div>
<p>This is still easy to read and makes the full power of type-annotated Python
available to ASCII believers.</p>
</section>
<section id="the-typedef-statement">
<h2><a class="toc-backref" href="#the-typedef-statement" role="doc-backlink">The <code class="docutils literal notranslate"><span class="pre">typedef</span></code> statement</a></h2>
<p>The mapping between types and declarators can be extended with this new statement.</p>
<p>The syntax is as follows:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">typedef_stmt</span> <span class="p">:</span><span class="o">:=</span> <span class="s2">&quot;typedef&quot;</span> <span class="n">expr</span> <span class="n">DECLARATOR</span>
</pre></div>
</div>
<p>where <code class="docutils literal notranslate"><span class="pre">expr</span></code> resolves to a type object. For convenience, the <code class="docutils literal notranslate"><span class="pre">typedef</span></code> statement
can also be mixed with the <code class="docutils literal notranslate"><span class="pre">class</span></code> statement for new classes, like so:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>typedef class Foo☺(object<63>):
pass
</pre></div>
</div>
</section>
<section id="example">
<h2><a class="toc-backref" href="#example" role="doc-backlink">Example</a></h2>
<p>This is the standard <code class="docutils literal notranslate"><span class="pre">os.path.normpath</span></code> function, converted to type declaration
syntax:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>def normpathƛ(path✎)✎:
&quot;&quot;&quot;Normalize path, eliminating double slashes, etc.&quot;&quot;&quot;
if path✎ == &#39;&#39;:
return &#39;.&#39;
initial_slashes✓ = path✎.startswithƛ(&#39;/&#39;)✓
# POSIX allows one or two initial slashes, but treats three or more
# as single slash.
if (initial_slashes✓ and
path✎.startswithƛ(&#39;//&#39;)✓ and not path✎.startswithƛ(&#39;///&#39;)✓)✓:
initial_slashes = 2
comps♨ = path✎.splitƛ(&#39;/&#39;)♨
new_comps♨ = []♨
for comp✎ in comps♨:
if comp✎ in (&#39;&#39;, &#39;.&#39;)⒯:
continue
if (comp✎ != &#39;..&#39; or (not initial_slashes and not new_comps♨)✓ or
(new_comps♨ and new_comps♨[-1]✎ == &#39;..&#39;)✓)✓:
new_comps♨.appendƛ(comp✎)
elif new_comps♨:
new_comps♨.popƛ()✎
comps♨ = new_comps♨
path✎ = &#39;/&#39;.join(comps♨)✎
if initial_slashes:
path✎ = &#39;/&#39;*initial_slashes + path✎
return path✎ or &#39;.&#39;
</pre></div>
</div>
<p>As you can clearly see, the type declarations add expressiveness, while at the
same time they make the code look much more professional.</p>
</section>
<section id="compatibility-issues">
<h2><a class="toc-backref" href="#compatibility-issues" role="doc-backlink">Compatibility issues</a></h2>
<p>To enable type declaration mode, one has to write:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">type_declarations</span>
</pre></div>
</div>
<p>which enables Unicode parsing of the source <a class="footnote-reference brackets" href="#id11" id="id7">[4]</a>, makes <code class="docutils literal notranslate"><span class="pre">typedef</span></code> a keyword
and enforces correct types for all assignments and function calls.</p>
</section>
<section id="rejection">
<h2><a class="toc-backref" href="#rejection" role="doc-backlink">Rejection</a></h2>
<p>After careful considering, much soul-searching, gnashing of teeth and rending
of garments, it has been decided to reject this PEP.</p>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<div role="list" class="citation-list">
<div class="citation" id="ex1" role="doc-biblioentry">
<dt class="label" id="ex1">[<a href="#id1">EX1</a>]</dt>
<dd><a class="reference external" href="https://mail.python.org/pipermail/python-list/2003-June/210588.html">https://mail.python.org/pipermail/python-list/2003-June/210588.html</a></div>
<div class="citation" id="ex2" role="doc-biblioentry">
<dt class="label" id="ex2">[<a href="#id2">EX2</a>]</dt>
<dd><a class="reference external" href="https://mail.python.org/pipermail/python-list/2000-May/034685.html">https://mail.python.org/pipermail/python-list/2000-May/034685.html</a></div>
<div class="citation" id="ex3" role="doc-biblioentry">
<dt class="label" id="ex3">[<a href="#id3">EX3</a>]</dt>
<dd><a class="reference external" href="http://groups.google.com/group/comp.lang.python/browse_frm/thread/6ae8c6add913635a/de40d4ffe9bd4304?lnk=gst&amp;q=type+declarations&amp;rnum=6">http://groups.google.com/group/comp.lang.python/browse_frm/thread/6ae8c6add913635a/de40d4ffe9bd4304?lnk=gst&amp;q=type+declarations&amp;rnum=6</a></div>
</div>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id8" role="doc-footnote">
<dt class="label" id="id8">[<a href="#id4">1</a>]</dt>
<dd>Though, if you know the language in question, it may not be <em>that</em> unrelated.</aside>
<aside class="footnote brackets" id="id9" role="doc-footnote">
<dt class="label" id="id9">[<a href="#id5">2</a>]</dt>
<dd>Well, it would, if there was a Perl 6.</aside>
<aside class="footnote brackets" id="id10" role="doc-footnote">
<dt class="label" id="id10">[<a href="#id6">3</a>]</dt>
<dd>Since the name <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> is already in use, this name has been chosen
for obvious reasons.</aside>
<aside class="footnote brackets" id="id11" role="doc-footnote">
<dt class="label" id="id11">[<a href="#id7">4</a>]</dt>
<dd>The encoding in which the code is written is read from a standard coding
cookie. There will also be an autodetection mechanism, invoked by <code class="docutils literal notranslate"><span class="pre">from</span>
<span class="pre">__future__</span> <span class="pre">import</span> <span class="pre">encoding_hell</span></code>.</aside>
</aside>
</section>
<section id="acknowledgements">
<h2><a class="toc-backref" href="#acknowledgements" role="doc-backlink">Acknowledgements</a></h2>
<p>Many thanks go to Armin Ronacher, Alexander Schremmer and Marek Kubica who helped
find the most suitable and mnemonic declarator for built-in types.</p>
<p>Thanks also to the Unicode Consortium for including all those useful characters
in the Unicode standard.</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-3117.rst">https://github.com/python/peps/blob/main/peps/pep-3117.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-3117.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="#specification">Specification</a></li>
<li><a class="reference internal" href="#unicode-replacement-units">Unicode replacement units</a></li>
<li><a class="reference internal" href="#the-typedef-statement">The <code class="docutils literal notranslate"><span class="pre">typedef</span></code> statement</a></li>
<li><a class="reference internal" href="#example">Example</a></li>
<li><a class="reference internal" href="#compatibility-issues">Compatibility issues</a></li>
<li><a class="reference internal" href="#rejection">Rejection</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#acknowledgements">Acknowledgements</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-3117.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>