python-peps/pep-3141/index.html

667 lines
55 KiB
HTML
Raw Permalink Normal View History

<!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 3141 A Type Hierarchy for Numbers | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-3141/">
<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 3141 A Type Hierarchy for Numbers | peps.python.org'>
<meta property="og:description" content="This proposal defines a hierarchy of Abstract Base Classes (ABCs) (PEP 3119) to represent number-like classes. It proposes a hierarchy of Number :&gt; Complex :&gt; Real :&gt; Rational :&gt; Integral where A :&gt; B means “A is a supertype of B”. The hierarchy is insp...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-3141/">
<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="This proposal defines a hierarchy of Abstract Base Classes (ABCs) (PEP 3119) to represent number-like classes. It proposes a hierarchy of Number :&gt; Complex :&gt; Real :&gt; Rational :&gt; Integral where A :&gt; B means “A is a supertype of B”. The hierarchy is insp...">
<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 3141</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 3141 A Type Hierarchy for Numbers</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Jeffrey Yasskin &lt;jyasskin&#32;&#97;t&#32;google.com&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</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-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">25-Apr-2007, 16-May-2007, 02-Aug-2007</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><ul>
<li><a class="reference internal" href="#numeric-classes">Numeric Classes</a></li>
<li><a class="reference internal" href="#changes-to-operations-and-magic-methods">Changes to operations and __magic__ methods</a></li>
<li><a class="reference internal" href="#notes-for-type-implementors">Notes for type implementors</a><ul>
<li><a class="reference internal" href="#adding-more-numeric-abcs">Adding More Numeric ABCs</a></li>
<li><a class="reference internal" href="#implementing-the-arithmetic-operations">Implementing the arithmetic operations</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#rejected-alternatives">Rejected Alternatives</a></li>
<li><a class="reference internal" href="#the-decimal-type">The Decimal Type</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 proposal defines a hierarchy of Abstract Base Classes (ABCs) (PEP
3119) to represent number-like classes. It proposes a hierarchy of
<code class="docutils literal notranslate"><span class="pre">Number</span> <span class="pre">:&gt;</span> <span class="pre">Complex</span> <span class="pre">:&gt;</span> <span class="pre">Real</span> <span class="pre">:&gt;</span> <span class="pre">Rational</span> <span class="pre">:&gt;</span> <span class="pre">Integral</span></code> where <code class="docutils literal notranslate"><span class="pre">A</span> <span class="pre">:&gt;</span> <span class="pre">B</span></code>
means “A is a supertype of B”. The hierarchy is inspired by Schemes
numeric tower <a class="footnote-reference brackets" href="#schemetower" id="id1">[3]</a>.</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>Functions that take numbers as arguments should be able to determine
the properties of those numbers, and if and when overloading based on
types is added to the language, should be overloadable based on the
types of the arguments. For example, slicing requires its arguments to
be <code class="docutils literal notranslate"><span class="pre">Integrals</span></code>, and the functions in the <code class="docutils literal notranslate"><span class="pre">math</span></code> module require
their arguments to be <code class="docutils literal notranslate"><span class="pre">Real</span></code>.</p>
</section>
<section id="specification">
<h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2>
<p>This PEP specifies a set of Abstract Base Classes, and suggests a
general strategy for implementing some of the methods. It uses
terminology from <a class="pep reference internal" href="../pep-3119/" title="PEP 3119 Introducing Abstract Base Classes">PEP 3119</a>, but the hierarchy is intended to be
meaningful for any systematic method of defining sets of classes.</p>
<p>The type checks in the standard library should use these classes
instead of the concrete built-ins.</p>
<section id="numeric-classes">
<h3><a class="toc-backref" href="#numeric-classes" role="doc-backlink">Numeric Classes</a></h3>
<p>We begin with a Number class to make it easy for people to be fuzzy
about what kind of number they expect. This class only helps with
overloading; it doesnt provide any operations.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Number</span><span class="p">(</span><span class="n">metaclass</span><span class="o">=</span><span class="n">ABCMeta</span><span class="p">):</span> <span class="k">pass</span>
</pre></div>
</div>
<p>Most implementations of complex numbers will be hashable, but if you
need to rely on that, youll have to check it explicitly: mutable
numbers are supported by this hierarchy.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Complex</span><span class="p">(</span><span class="n">Number</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Complex defines the operations that work on the builtin complex type.</span>
<span class="sd"> In short, those are: conversion to complex, bool(), .real, .imag,</span>
<span class="sd"> +, -, *, /, **, abs(), .conjugate(), ==, and !=.</span>
<span class="sd"> If it is given heterogeneous arguments, and doesn&#39;t have special</span>
<span class="sd"> knowledge about them, it should fall back to the builtin complex</span>
<span class="sd"> type as described below.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="fm">__complex__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Return a builtin complex instance.&quot;&quot;&quot;</span>
<span class="k">def</span> <span class="fm">__bool__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;True if self != 0.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span> <span class="o">!=</span> <span class="mi">0</span>
<span class="nd">@abstractproperty</span>
<span class="k">def</span> <span class="nf">real</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Retrieve the real component of this number.</span>
<span class="sd"> This should subclass Real.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="nd">@abstractproperty</span>
<span class="k">def</span> <span class="nf">imag</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Retrieve the imaginary component of this number.</span>
<span class="sd"> This should subclass Real.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="fm">__add__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="fm">__radd__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="fm">__neg__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="k">def</span> <span class="fm">__pos__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Coerces self to whatever class defines the method.&quot;&quot;&quot;</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="k">def</span> <span class="fm">__sub__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span> <span class="o">+</span> <span class="o">-</span><span class="n">other</span>
<span class="k">def</span> <span class="fm">__rsub__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">return</span> <span class="o">-</span><span class="bp">self</span> <span class="o">+</span> <span class="n">other</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="fm">__mul__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="fm">__rmul__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="nf">__div__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;a/b; should promote to float or complex when necessary.&quot;&quot;&quot;</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="nf">__rdiv__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="fm">__pow__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exponent</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;a**b; should promote to float or complex when necessary.&quot;&quot;&quot;</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="fm">__rpow__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">base</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="fm">__abs__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Returns the Real distance from 0.&quot;&quot;&quot;</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="nf">conjugate</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;(x+y*i).conjugate() returns (x-y*i).&quot;&quot;&quot;</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="fm">__eq__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="c1"># __ne__ is inherited from object and negates whatever __eq__ does.</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">Real</span></code> ABC indicates that the value is on the real line, and
supports the operations of the <code class="docutils literal notranslate"><span class="pre">float</span></code> builtin. Real numbers are
totally ordered except for NaNs (which this PEP basically ignores).</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Real</span><span class="p">(</span><span class="n">Complex</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;To Complex, Real adds the operations that work on real numbers.</span>
<span class="sd"> In short, those are: conversion to float, trunc(), math.floor(),</span>
<span class="sd"> math.ceil(), round(), divmod(), //, %, &lt;, &lt;=, &gt;, and &gt;=.</span>
<span class="sd"> Real also provides defaults for some of the derived operations.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="c1"># XXX What to do about the __int__ implementation that&#39;s</span>
<span class="c1"># currently present on float? Get rid of it?</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="fm">__float__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Any Real can be converted to a native float object.&quot;&quot;&quot;</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="nf">__trunc__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Truncates self to an Integral.</span>
<span class="sd"> Returns an Integral i such that:</span>
<span class="sd"> * i&gt;=0 iff self&gt;0;</span>
<span class="sd"> * abs(i) &lt;= abs(self);</span>
<span class="sd"> * for any Integral j satisfying the first two conditions,</span>
<span class="sd"> abs(i) &gt;= abs(j) [i.e. i has &quot;maximal&quot; abs among those].</span>
<span class="sd"> i.e. &quot;truncate towards 0&quot;.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="nf">__floor__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Finds the greatest Integral &lt;= self.&quot;&quot;&quot;</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="nf">__ceil__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Finds the least Integral &gt;= self.&quot;&quot;&quot;</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="fm">__round__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">ndigits</span><span class="p">:</span><span class="n">Integral</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Rounds self to ndigits decimal places, defaulting to 0.</span>
<span class="sd"> If ndigits is omitted or None, returns an Integral,</span>
<span class="sd"> otherwise returns a Real, preferably of the same type as</span>
<span class="sd"> self. Types may choose which direction to round half. For</span>
<span class="sd"> example, float rounds half toward even.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="k">def</span> <span class="fm">__divmod__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;The pair (self // other, self % other).</span>
<span class="sd"> Sometimes this can be computed faster than the pair of</span>
<span class="sd"> operations.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="p">(</span><span class="bp">self</span> <span class="o">//</span> <span class="n">other</span><span class="p">,</span> <span class="bp">self</span> <span class="o">%</span> <span class="n">other</span><span class="p">)</span>
<span class="k">def</span> <span class="fm">__rdivmod__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;The pair (self // other, self % other).</span>
<span class="sd"> Sometimes this can be computed faster than the pair of</span>
<span class="sd"> operations.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="p">(</span><span class="n">other</span> <span class="o">//</span> <span class="bp">self</span><span class="p">,</span> <span class="n">other</span> <span class="o">%</span> <span class="bp">self</span><span class="p">)</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="fm">__floordiv__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;The floor() of self/other. Integral.&quot;&quot;&quot;</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="fm">__rfloordiv__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;The floor() of other/self.&quot;&quot;&quot;</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="fm">__mod__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;self % other</span>
<span class="sd"> See</span>
<span class="sd"> https://mail.python.org/pipermail/python-3000/2006-May/001735.html</span>
<span class="sd"> and consider using &quot;self/other - trunc(self/other)&quot;</span>
<span class="sd"> instead if you&#39;re worried about round-off errors.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="fm">__rmod__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;other % self&quot;&quot;&quot;</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="fm">__lt__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;&lt; on Reals defines a total ordering, except perhaps for NaN.&quot;&quot;&quot;</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="fm">__le__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="c1"># __gt__ and __ge__ are automatically done by reversing the arguments.</span>
<span class="c1"># (But __le__ is not computed as the opposite of __gt__!)</span>
<span class="c1"># Concrete implementations of Complex abstract methods.</span>
<span class="c1"># Subclasses may override these, but don&#39;t have to.</span>
<span class="k">def</span> <span class="fm">__complex__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">complex</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="bp">self</span><span class="p">))</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">real</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="o">+</span><span class="bp">self</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">imag</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="mi">0</span>
<span class="k">def</span> <span class="nf">conjugate</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Conjugate is a no-op for Reals.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="o">+</span><span class="bp">self</span>
</pre></div>
</div>
<p>We should clean up Demo/classes/Rat.py and promote it into
rational.py in the standard library. Then it will implement the
Rational ABC.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Rational</span><span class="p">(</span><span class="n">Real</span><span class="p">,</span> <span class="n">Exact</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;.numerator and .denominator should be in lowest terms.&quot;&quot;&quot;</span>
<span class="nd">@abstractproperty</span>
<span class="k">def</span> <span class="nf">numerator</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="nd">@abstractproperty</span>
<span class="k">def</span> <span class="nf">denominator</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="c1"># Concrete implementation of Real&#39;s conversion to float.</span>
<span class="c1"># (This invokes Integer.__div__().)</span>
<span class="k">def</span> <span class="fm">__float__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">numerator</span> <span class="o">/</span> <span class="bp">self</span><span class="o">.</span><span class="n">denominator</span>
</pre></div>
</div>
<p>And finally integers:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Integral</span><span class="p">(</span><span class="n">Rational</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Integral adds a conversion to int and the bit-string operations.&quot;&quot;&quot;</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="fm">__int__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="k">def</span> <span class="fm">__index__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;__index__() exists because float has __int__().&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="k">def</span> <span class="fm">__lshift__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="nb">int</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
<span class="k">def</span> <span class="fm">__rlshift__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">other</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="k">def</span> <span class="fm">__rshift__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="nb">int</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
<span class="k">def</span> <span class="fm">__rrshift__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">other</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="k">def</span> <span class="fm">__and__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">&amp;</span> <span class="nb">int</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
<span class="k">def</span> <span class="fm">__rand__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">other</span><span class="p">)</span> <span class="o">&amp;</span> <span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="k">def</span> <span class="fm">__xor__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">^</span> <span class="nb">int</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
<span class="k">def</span> <span class="fm">__rxor__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">other</span><span class="p">)</span> <span class="o">^</span> <span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="k">def</span> <span class="fm">__or__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">|</span> <span class="nb">int</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
<span class="k">def</span> <span class="fm">__ror__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">other</span><span class="p">)</span> <span class="o">|</span> <span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="k">def</span> <span class="fm">__invert__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="o">~</span><span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="c1"># Concrete implementations of Rational and Real abstract methods.</span>
<span class="k">def</span> <span class="fm">__float__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;float(self) == float(int(self))&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="nb">float</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="p">))</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">numerator</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Integers are their own numerators.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="o">+</span><span class="bp">self</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">denominator</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Integers have a denominator of 1.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="mi">1</span>
</pre></div>
</div>
</section>
<section id="changes-to-operations-and-magic-methods">
<h3><a class="toc-backref" href="#changes-to-operations-and-magic-methods" role="doc-backlink">Changes to operations and __magic__ methods</a></h3>
<p>To support more precise narrowing from float to int (and more
generally, from Real to Integral), we propose the following new
__magic__ methods, to be called from the corresponding library
functions. All of these return Integrals rather than Reals.</p>
<ol class="arabic simple">
<li><code class="docutils literal notranslate"><span class="pre">__trunc__(self)</span></code>, called from a new builtin <code class="docutils literal notranslate"><span class="pre">trunc(x)</span></code>, which
returns the Integral closest to <code class="docutils literal notranslate"><span class="pre">x</span></code> between 0 and <code class="docutils literal notranslate"><span class="pre">x</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">__floor__(self)</span></code>, called from <code class="docutils literal notranslate"><span class="pre">math.floor(x)</span></code>, which returns
the greatest Integral <code class="docutils literal notranslate"><span class="pre">&lt;=</span> <span class="pre">x</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">__ceil__(self)</span></code>, called from <code class="docutils literal notranslate"><span class="pre">math.ceil(x)</span></code>, which returns the
least Integral <code class="docutils literal notranslate"><span class="pre">&gt;=</span> <span class="pre">x</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">__round__(self)</span></code>, called from <code class="docutils literal notranslate"><span class="pre">round(x)</span></code>, which returns the
Integral closest to <code class="docutils literal notranslate"><span class="pre">x</span></code>, rounding half as the type chooses.
<code class="docutils literal notranslate"><span class="pre">float</span></code> will change in 3.0 to round half toward even. There is
also a 2-argument version, <code class="docutils literal notranslate"><span class="pre">__round__(self,</span> <span class="pre">ndigits)</span></code>, called
from <code class="docutils literal notranslate"><span class="pre">round(x,</span> <span class="pre">ndigits)</span></code>, which should return a Real.</li>
</ol>
<p>In 2.6, <code class="docutils literal notranslate"><span class="pre">math.floor</span></code>, <code class="docutils literal notranslate"><span class="pre">math.ceil</span></code>, and <code class="docutils literal notranslate"><span class="pre">round</span></code> will continue to
return floats.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">int()</span></code> conversion implemented by <code class="docutils literal notranslate"><span class="pre">float</span></code> is equivalent to
<code class="docutils literal notranslate"><span class="pre">trunc()</span></code>. In general, the <code class="docutils literal notranslate"><span class="pre">int()</span></code> conversion should try
<code class="docutils literal notranslate"><span class="pre">__int__()</span></code> first and if it is not found, try <code class="docutils literal notranslate"><span class="pre">__trunc__()</span></code>.</p>
<p><code class="docutils literal notranslate"><span class="pre">complex.__{divmod,mod,floordiv,int,float}__</span></code> also go away. It would
be nice to provide a nice error message to help confused porters, but
not appearing in <code class="docutils literal notranslate"><span class="pre">help(complex)</span></code> is more important.</p>
</section>
<section id="notes-for-type-implementors">
<h3><a class="toc-backref" href="#notes-for-type-implementors" role="doc-backlink">Notes for type implementors</a></h3>
<p>Implementors should be careful to make equal numbers equal and
hash them to the same values. This may be subtle if there are two
different extensions of the real numbers. For example, a complex type
could reasonably implement hash() as follows:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="fm">__hash__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">hash</span><span class="p">(</span><span class="nb">complex</span><span class="p">(</span><span class="bp">self</span><span class="p">))</span>
</pre></div>
</div>
<p>but should be careful of any values that fall outside of the built in
complexs range or precision.</p>
<section id="adding-more-numeric-abcs">
<h4><a class="toc-backref" href="#adding-more-numeric-abcs" role="doc-backlink">Adding More Numeric ABCs</a></h4>
<p>There are, of course, more possible ABCs for numbers, and this would
be a poor hierarchy if it precluded the possibility of adding
those. You can add <code class="docutils literal notranslate"><span class="pre">MyFoo</span></code> between <code class="docutils literal notranslate"><span class="pre">Complex</span></code> and <code class="docutils literal notranslate"><span class="pre">Real</span></code> with:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">MyFoo</span><span class="p">(</span><span class="n">Complex</span><span class="p">):</span> <span class="o">...</span>
<span class="n">MyFoo</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">Real</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="implementing-the-arithmetic-operations">
<h4><a class="toc-backref" href="#implementing-the-arithmetic-operations" role="doc-backlink">Implementing the arithmetic operations</a></h4>
<p>We want to implement the arithmetic operations so that mixed-mode
operations either call an implementation whose author knew about the
types of both arguments, or convert both to the nearest built in type
and do the operation there. For subtypes of Integral, this means that
__add__ and __radd__ should be defined as:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">MyIntegral</span><span class="p">(</span><span class="n">Integral</span><span class="p">):</span>
<span class="k">def</span> <span class="fm">__add__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">MyIntegral</span><span class="p">):</span>
<span class="k">return</span> <span class="n">do_my_adding_stuff</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">)</span>
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">OtherTypeIKnowAbout</span><span class="p">):</span>
<span class="k">return</span> <span class="n">do_my_other_adding_stuff</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">NotImplemented</span>
<span class="k">def</span> <span class="fm">__radd__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">MyIntegral</span><span class="p">):</span>
<span class="k">return</span> <span class="n">do_my_adding_stuff</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span>
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">OtherTypeIKnowAbout</span><span class="p">):</span>
<span class="k">return</span> <span class="n">do_my_other_adding_stuff</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span>
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">Integral</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">other</span><span class="p">)</span> <span class="o">+</span> <span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">Real</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">float</span><span class="p">(</span><span class="n">other</span><span class="p">)</span> <span class="o">+</span> <span class="nb">float</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">Complex</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">complex</span><span class="p">(</span><span class="n">other</span><span class="p">)</span> <span class="o">+</span> <span class="nb">complex</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">NotImplemented</span>
</pre></div>
</div>
<p>There are 5 different cases for a mixed-type operation on subclasses
of Complex. Ill refer to all of the above code that doesnt refer to
MyIntegral and OtherTypeIKnowAbout as “boilerplate”. <code class="docutils literal notranslate"><span class="pre">a</span></code> will be an
instance of <code class="docutils literal notranslate"><span class="pre">A</span></code>, which is a subtype of <code class="docutils literal notranslate"><span class="pre">Complex</span></code> (<code class="docutils literal notranslate"><span class="pre">a</span> <span class="pre">:</span> <span class="pre">A</span> <span class="pre">&lt;:</span>
<span class="pre">Complex</span></code>), and <code class="docutils literal notranslate"><span class="pre">b</span> <span class="pre">:</span> <span class="pre">B</span> <span class="pre">&lt;:</span> <span class="pre">Complex</span></code>. Ill consider <code class="docutils literal notranslate"><span class="pre">a</span> <span class="pre">+</span> <span class="pre">b</span></code>:</p>
<ol class="arabic simple">
<li>If A defines an __add__ which accepts b, all is well.</li>
<li>If A falls back to the boilerplate code, and it were to return
a value from __add__, wed miss the possibility that B defines
a more intelligent __radd__, so the boilerplate should return
NotImplemented from __add__. (Or A may not implement __add__ at
all.)</li>
<li>Then Bs __radd__ gets a chance. If it accepts a, all is well.</li>
<li>If it falls back to the boilerplate, there are no more possible
methods to try, so this is where the default implementation
should live.</li>
<li>If B &lt;: A, Python tries B.__radd__ before A.__add__. This is
ok, because it was implemented with knowledge of A, so it can
handle those instances before delegating to Complex.</li>
</ol>
<p>If <code class="docutils literal notranslate"><span class="pre">A&lt;:Complex</span></code> and <code class="docutils literal notranslate"><span class="pre">B&lt;:Real</span></code> without sharing any other knowledge,
then the appropriate shared operation is the one involving the built
in complex, and both __radd__s land there, so <code class="docutils literal notranslate"><span class="pre">a+b</span> <span class="pre">==</span> <span class="pre">b+a</span></code>.</p>
</section>
</section>
</section>
<section id="rejected-alternatives">
<h2><a class="toc-backref" href="#rejected-alternatives" role="doc-backlink">Rejected Alternatives</a></h2>
<p>The initial version of this PEP defined an algebraic hierarchy
inspired by a Haskell Numeric Prelude <a class="footnote-reference brackets" href="#numericprelude" id="id2">[2]</a> including
MonoidUnderPlus, AdditiveGroup, Ring, and Field, and mentioned several
other possible algebraic types before getting to the numbers. We had
expected this to be useful to people using vectors and matrices, but
the NumPy community really wasnt interested, and we ran into the
issue that even if <code class="docutils literal notranslate"><span class="pre">x</span></code> is an instance of <code class="docutils literal notranslate"><span class="pre">X</span> <span class="pre">&lt;:</span> <span class="pre">MonoidUnderPlus</span></code>
and <code class="docutils literal notranslate"><span class="pre">y</span></code> is an instance of <code class="docutils literal notranslate"><span class="pre">Y</span> <span class="pre">&lt;:</span> <span class="pre">MonoidUnderPlus</span></code>, <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">+</span> <span class="pre">y</span></code> may
still not make sense.</p>
<p>Then we gave the numbers a much more branching structure to include
things like the Gaussian Integers and Z/nZ, which could be Complex but
wouldnt necessarily support things like division. The community
decided that this was too much complication for Python, so Ive now
scaled back the proposal to resemble the Scheme numeric tower much
more closely.</p>
</section>
<section id="the-decimal-type">
<h2><a class="toc-backref" href="#the-decimal-type" role="doc-backlink">The Decimal Type</a></h2>
<p>After consultation with its authors it has been decided that the
<code class="docutils literal notranslate"><span class="pre">Decimal</span></code> type should not at this time be made part of the numeric
tower.</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="classtree" role="doc-footnote">
<dt class="label" id="classtree">[1]</dt>
<dd>Possible Python 3K Class Tree?, wiki page by Bill Janssen
(<a class="reference external" href="http://wiki.python.org/moin/AbstractBaseClasses">http://wiki.python.org/moin/AbstractBaseClasses</a>)</aside>
<aside class="footnote brackets" id="numericprelude" role="doc-footnote">
<dt class="label" id="numericprelude">[<a href="#id2">2</a>]</dt>
<dd>NumericPrelude: An experimental alternative hierarchy
of numeric type classes
(<a class="reference external" href="https://archives.haskell.org/code.haskell.org/numeric-prelude/docs/html/index.html">https://archives.haskell.org/code.haskell.org/numeric-prelude/docs/html/index.html</a>)</aside>
<aside class="footnote brackets" id="schemetower" role="doc-footnote">
<dt class="label" id="schemetower">[<a href="#id1">3</a>]</dt>
<dd>The Scheme numerical tower
(<a class="reference external" href="https://groups.csail.mit.edu/mac/ftpdir/scheme-reports/r5rs-html/r5rs_8.html#SEC50">https://groups.csail.mit.edu/mac/ftpdir/scheme-reports/r5rs-html/r5rs_8.html#SEC50</a>)</aside>
</aside>
</section>
<section id="acknowledgements">
<h2><a class="toc-backref" href="#acknowledgements" role="doc-backlink">Acknowledgements</a></h2>
<p>Thanks to Neal Norwitz for encouraging me to write this PEP in the
first place, to Travis Oliphant for pointing out that the numpy people
didnt really care about the algebraic concepts, to Alan Isaac for
reminding me that Scheme had already done this, and to Guido van
Rossum and lots of other people on the mailing list for refining the
concept.</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-3141.rst">https://github.com/python/peps/blob/main/peps/pep-3141.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-3141.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><ul>
<li><a class="reference internal" href="#numeric-classes">Numeric Classes</a></li>
<li><a class="reference internal" href="#changes-to-operations-and-magic-methods">Changes to operations and __magic__ methods</a></li>
<li><a class="reference internal" href="#notes-for-type-implementors">Notes for type implementors</a><ul>
<li><a class="reference internal" href="#adding-more-numeric-abcs">Adding More Numeric ABCs</a></li>
<li><a class="reference internal" href="#implementing-the-arithmetic-operations">Implementing the arithmetic operations</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#rejected-alternatives">Rejected Alternatives</a></li>
<li><a class="reference internal" href="#the-decimal-type">The Decimal Type</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-3141.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>