uTools-Manuals/docs/python/numbers.html
2019-04-21 11:50:48 +08:00

74 lines
32 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<div class="body" role="main"><div class="section" id="module-numbers"><h1><span class="yiyi-st" id="yiyi-10">9.1. <a class="reference internal" href="#module-numbers" title="numbers: Numeric abstract base classes (Complex, Real, Integral, etc.)."><code class="xref py py-mod docutils literal"><span class="pre">numbers</span></code></a> - 数字抽象基类</span></h1><p><span class="yiyi-st" id="yiyi-11"><strong>源代码:</strong> <a class="reference external" href="https://hg.python.org/cpython/file/3.5/Lib/numbers.py">Lib/numbers.py</a></span></p><p><span class="yiyi-st" id="yiyi-12"><a class="reference internal" href="#module-numbers" title="numbers: Numeric abstract base classes (Complex, Real, Integral, etc.)."><code class="xref py py-mod docutils literal"><span class="pre">numbers</span></code></a>模块(<span class="target" id="index-0"></span> <a class="pep reference external" href="https://www.python.org/dev/peps/pep-3141"><strong>PEP 3141</strong></a>)定义了逐渐定义更多操作的数字<a class="reference internal" href="../glossary.html#term-abstract-base-class"><span class="xref std std-term">abstract base classes</span></a>的层次结构。</span><span class="yiyi-st" id="yiyi-13">本模块中定义的任何类型,都不能被实例化。</span></p><dl class="class"><dt id="numbers.Number"><span class="yiyi-st" id="yiyi-14"><em class="property">class </em><code class="descclassname">numbers.</code><code class="descname">Number</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-15">数字层次结构的根。</span><span class="yiyi-st" id="yiyi-16">如果只想检查参数<em>x</em>是否为数字,而不考虑什么类型,请使用<code class="docutils literal"><span class="pre">isinstancex</span> <span class="pre">Number</span> </code></span></p></dd></dl><div class="section" id="the-numeric-tower"><h2><span class="yiyi-st" id="yiyi-17">9.1.1.</span><span class="yiyi-st" id="yiyi-18">The numeric tower</span></h2><dl class="class"><dt id="numbers.Complex"><span class="yiyi-st" id="yiyi-19"><em class="property">class </em><code class="descclassname">numbers.</code><code class="descname">Complex</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-20">此类型的子类描述复数,并包括对内建<a class="reference internal" href="functions.html#complex" title="complex"><code class="xref py py-class docutils literal"><span class="pre">complex</span></code></a>类型工作的操作。</span><span class="yiyi-st" id="yiyi-21">These are: conversions to <a class="reference internal" href="functions.html#complex" title="complex"><code class="xref py py-class docutils literal"><span class="pre">complex</span></code></a> and <a class="reference internal" href="functions.html#bool" title="bool"><code class="xref py py-class docutils literal"><span class="pre">bool</span></code></a>, <a class="reference internal" href="#numbers.Complex.real" title="numbers.Complex.real"><code class="xref py py-attr docutils literal"><span class="pre">real</span></code></a>, <a class="reference internal" href="#numbers.Complex.imag" title="numbers.Complex.imag"><code class="xref py py-attr docutils literal"><span class="pre">imag</span></code></a>, <code class="docutils literal"><span class="pre">+</span></code>, <code class="docutils literal"><span class="pre">-</span></code>, <code class="docutils literal"><span class="pre">*</span></code>, <code class="docutils literal"><span class="pre">/</span></code>, <a class="reference internal" href="functions.html#abs" title="abs"><code class="xref py py-func docutils literal"><span class="pre">abs()</span></code></a>, <a class="reference internal" href="#numbers.Complex.conjugate" title="numbers.Complex.conjugate"><code class="xref py py-meth docutils literal"><span class="pre">conjugate()</span></code></a>, <code class="docutils literal"><span class="pre">==</span></code>, and <code class="docutils literal"><span class="pre">!=</span></code>. </span><span class="yiyi-st" id="yiyi-22"><code class="docutils literal"><span class="pre">-</span></code><code class="docutils literal"><span class="pre">!=</span></code>之外的都是抽象的。</span></p><dl class="attribute"><dt id="numbers.Complex.real"><span class="yiyi-st" id="yiyi-23"><code class="descname">real</code> </span></dt><dd><p><span class="yiyi-st" id="yiyi-24">抽象。</span><span class="yiyi-st" id="yiyi-25">检索此数的实部。</span></p></dd></dl><dl class="attribute"><dt id="numbers.Complex.imag"><span class="yiyi-st" id="yiyi-26"><code class="descname">imag</code> </span></dt><dd><p><span class="yiyi-st" id="yiyi-27">抽象。</span><span class="yiyi-st" id="yiyi-28">检索此数的虚部。</span></p></dd></dl><dl class="method"><dt id="numbers.Complex.conjugate"><span class="yiyi-st" id="yiyi-29"><em class="property">abstractmethod </em><code class="descname">conjugate</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-30">抽象。</span><span class="yiyi-st" id="yiyi-31">返回共轭复数。</span><span class="yiyi-st" id="yiyi-32">例如,<code class="docutils literal"><span class="pre">1 + 3j.conjugate()</span> <span class="pre">==</span> <span class="pre">1-3j</span></code></span></p></dd></dl></dd></dl><dl class="class"><dt id="numbers.Real"><span class="yiyi-st" id="yiyi-33"><em class="property">class </em><code class="descclassname">numbers.</code><code class="descname">Real</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-34"><a class="reference internal" href="#numbers.Complex" title="numbers.Complex"><code class="xref py py-class docutils literal"><span class="pre">Complex</span></code></a><a class="reference internal" href="#numbers.Real" title="numbers.Real"><code class="xref py py-class docutils literal"><span class="pre">Real</span></code></a>添加了对实数起作用的操作。</span></p><p><span class="yiyi-st" id="yiyi-35">In short, those are: a conversion to <a class="reference internal" href="functions.html#float" title="float"><code class="xref py py-class docutils literal"><span class="pre">float</span></code></a>, <a class="reference internal" href="math.html#math.trunc" title="math.trunc"><code class="xref py py-func docutils literal"><span class="pre">math.trunc()</span></code></a>, <a class="reference internal" href="functions.html#round" title="round"><code class="xref py py-func docutils literal"><span class="pre">round()</span></code></a>, <a class="reference internal" href="math.html#math.floor" title="math.floor"><code class="xref py py-func docutils literal"><span class="pre">math.floor()</span></code></a>, <a class="reference internal" href="math.html#math.ceil" title="math.ceil"><code class="xref py py-func docutils literal"><span class="pre">math.ceil()</span></code></a>, <a class="reference internal" href="functions.html#divmod" title="divmod"><code class="xref py py-func docutils literal"><span class="pre">divmod()</span></code></a>, <code class="docutils literal"><span class="pre">//</span></code>, <code class="docutils literal"><span class="pre">%</span></code>, <code class="docutils literal"><span class="pre">&lt;</span></code>, <code class="docutils literal"><span class="pre">&lt;=</span></code>, <code class="docutils literal"><span class="pre">&gt;</span></code>, and <code class="docutils literal"><span class="pre">&gt;=</span></code>.</span></p><p><span class="yiyi-st" id="yiyi-36">Real还为<a class="reference internal" href="functions.html#complex" title="complex"><code class="xref py py-func docutils literal"><span class="pre">complex()</span></code></a><a class="reference internal" href="#numbers.Complex.real" title="numbers.Complex.real"><code class="xref py py-attr docutils literal"><span class="pre">real</span></code></a><a class="reference internal" href="#numbers.Complex.imag" title="numbers.Complex.imag"><code class="xref py py-attr docutils literal"><span class="pre">imag</span></code></a><a class="reference internal" href="#numbers.Complex.conjugate" title="numbers.Complex.conjugate"><code class="xref py py-meth docutils literal"><span class="pre">conjugate()</span></code></a>提供默认值。</span></p></dd></dl><dl class="class"><dt id="numbers.Rational"><span class="yiyi-st" id="yiyi-37"><em class="property">class </em><code class="descclassname">numbers.</code><code class="descname">Rational</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-38">子类型<a class="reference internal" href="#numbers.Real" title="numbers.Real"><code class="xref py py-class docutils literal"><span class="pre">Real</span></code></a>并添加<a class="reference internal" href="#numbers.Rational.numerator" title="numbers.Rational.numerator"><code class="xref py py-attr docutils literal"><span class="pre">numerator</span></code></a><a class="reference internal" href="#numbers.Rational.denominator" title="numbers.Rational.denominator"><code class="xref py py-attr docutils literal"><span class="pre">denominator</span></code></a>属性,这些属性应为最低值。</span><span class="yiyi-st" id="yiyi-39">有了这些,它提供了<a class="reference internal" href="functions.html#float" title="float"><code class="xref py py-func docutils literal"><span class="pre">float()</span></code></a>的默认值。</span></p><dl class="attribute"><dt id="numbers.Rational.numerator"><span class="yiyi-st" id="yiyi-40"><code class="descname">numerator</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-41">抽象。</span></p></dd></dl><dl class="attribute"><dt id="numbers.Rational.denominator"><span class="yiyi-st" id="yiyi-42"><code class="descname">denominator</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-43">抽象。</span></p></dd></dl></dd></dl><dl class="class"><dt id="numbers.Integral"><span class="yiyi-st" id="yiyi-44"><em class="property">class </em><code class="descclassname">numbers.</code><code class="descname">Integral</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-45">子类型<a class="reference internal" href="#numbers.Rational" title="numbers.Rational"><code class="xref py py-class docutils literal"><span class="pre">Rational</span></code></a>,并向<a class="reference internal" href="functions.html#int" title="int"><code class="xref py py-class docutils literal"><span class="pre">int</span></code></a>添加转换。</span><span class="yiyi-st" id="yiyi-46">提供<a class="reference internal" href="functions.html#float" title="float"><code class="xref py py-func docutils literal"><span class="pre">float()</span></code></a><a class="reference internal" href="#numbers.Rational.numerator" title="numbers.Rational.numerator"><code class="xref py py-attr docutils literal"><span class="pre">numerator</span></code></a><a class="reference internal" href="#numbers.Rational.denominator" title="numbers.Rational.denominator"><code class="xref py py-attr docutils literal"><span class="pre">denominator</span></code></a>的默认值。</span><span class="yiyi-st" id="yiyi-47">Adds abstract methods for <code class="docutils literal"><span class="pre">**</span></code> and bit-string operations: <code class="docutils literal"><span class="pre">&lt;&lt;</span></code>, <code class="docutils literal"><span class="pre">&gt;&gt;</span></code>, <code class="docutils literal"><span class="pre">&amp;</span></code>, <code class="docutils literal"><span class="pre">^</span></code>, <code class="docutils literal"><span class="pre">|</span></code>, <code class="docutils literal"><span class="pre">~</span></code>.</span></p></dd></dl></div><div class="section" id="notes-for-type-implementors"><h2><span class="yiyi-st" id="yiyi-48">9.1.2.</span><span class="yiyi-st" id="yiyi-49">类型实现的注意事项</span></h2><p><span class="yiyi-st" id="yiyi-50">执行者要小心使相等的数字相等和散列他们为相同的值。</span><span class="yiyi-st" id="yiyi-51">这可能是实数的微妙的如果有两个不同的扩展。</span><span class="yiyi-st" id="yiyi-52">例如,<a class="reference internal" href="fractions.html#fractions.Fraction" title="fractions.Fraction"><code class="xref py py-class docutils literal"><span class="pre">fractions.Fraction</span></code></a>实现<a class="reference internal" href="functions.html#hash" title="hash"><code class="xref py py-func docutils literal"><span class="pre">hash()</span></code></a>如下:</span></p><pre><code class="language-python"><span></span><span class="k">def</span> <span class="nf">__hash__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">denominator</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="c1"># Get integers right.</span>
<span class="k">return</span> <span class="nb">hash</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">numerator</span><span class="p">)</span>
<span class="c1"># Expensive check, but definitely correct.</span>
<span class="k">if</span> <span class="bp">self</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">return</span> <span class="nb">hash</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="k">else</span><span class="p">:</span>
<span class="c1"># Use tuple's hash to avoid a high collision rate on</span>
<span class="c1"># simple fractions.</span>
<span class="k">return</span> <span class="nb">hash</span><span class="p">((</span><span class="bp">self</span><span class="o">.</span><span class="n">numerator</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">denominator</span><span class="p">))</span>
</code></pre><div class="section" id="adding-more-numeric-abcs"><h3><span class="yiyi-st" id="yiyi-53">9.1.2.1.</span><span class="yiyi-st" id="yiyi-54">添加更多数字ABCS </span></h3><p><span class="yiyi-st" id="yiyi-55">当然,有数字,更有可能基本要领,如果它排除了那些增加的可能性,这将是糟糕的层次结构。</span><span class="yiyi-st" id="yiyi-56">您可以在<a class="reference internal" href="#numbers.Complex" title="numbers.Complex"><code class="xref py py-class docutils literal"><span class="pre">Complex</span></code></a><a class="reference internal" href="#numbers.Real" title="numbers.Real"><code class="xref py py-class docutils literal"><span class="pre">Real</span></code></a>之间添加<code class="docutils literal"><span class="pre">MyFoo</span></code></span></p><pre><code class="language-python"><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>
</code></pre></div><div class="section" id="implementing-the-arithmetic-operations"><h3><span class="yiyi-st" id="yiyi-57">9.1.2.2.</span><span class="yiyi-st" id="yiyi-58">实现算术运算</span></h3><p><span class="yiyi-st" id="yiyi-59">我们想要实现的算术运算,以便混合模式操作调用的作者知道这两个参数的类型的实现或都转换为最近内建类型和那里操作。</span><span class="yiyi-st" id="yiyi-60">对于子类型<a class="reference internal" href="#numbers.Integral" title="numbers.Integral"><code class="xref py py-class docutils literal"><span class="pre">Integral</span></code></a>,这意味着<a class="reference internal" href="../reference/datamodel.html#object.__add__" title="object.__add__"><code class="xref py py-meth docutils literal"><span class="pre">__add__()</span></code></a><a class="reference internal" href="../reference/datamodel.html#object.__radd__" title="object.__radd__"><code class="xref py py-meth docutils literal"><span class="pre">__radd__()</span></code></a>应定义为:</span></p><pre><code class="language-python"><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="nf">__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="nf">__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>
</code></pre><p><span class="yiyi-st" id="yiyi-61">对于<a class="reference internal" href="#numbers.Complex" title="numbers.Complex"><code class="xref py py-class docutils literal"><span class="pre">Complex</span></code></a>的子类的混合类型操作有5种不同的情况。</span><span class="yiyi-st" id="yiyi-62">我将引用所有上述代码,不将<code class="docutils literal"><span class="pre">MyIntegral</span></code><code class="docutils literal"><span class="pre">OtherTypeIKnowAbout</span></code>称为“样板”。</span><span class="yiyi-st" id="yiyi-63"><code class="docutils literal"><span class="pre">a</span></code> will be an instance of <code class="docutils literal"><span class="pre">A</span></code>, which is a subtype of <a class="reference internal" href="#numbers.Complex" title="numbers.Complex"><code class="xref py py-class docutils literal"><span class="pre">Complex</span></code></a> (<code class="docutils literal"><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"><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>. </span><span class="yiyi-st" id="yiyi-64">我会考虑<code class="docutils literal"><span class="pre">a</span> <span class="pre">+</span> <span class="pre">b</span></code></span></p><span class="yiyi-st" id="yiyi-68"> <blockquote> <div><ol class="arabic simple"> <li>If <code class="docutils literal"><span class="pre">A</span></code> defines an <a class="reference internal" href="../reference/datamodel.html#object.__add__" title="object.__add__"><code class="xref py py-meth docutils literal"><span class="pre">__add__()</span></code></a> which accepts <code class="docutils literal"><span class="pre">b</span></code>, all is well.</li> <li>If <code class="docutils literal"><span class="pre">A</span></code> falls back to the boilerplate code, and it were to return a value from <a class="reference internal" href="../reference/datamodel.html#object.__add__" title="object.__add__"><code class="xref py py-meth docutils literal"><span class="pre">__add__()</span></code></a>, wed miss the possibility that <code class="docutils literal"><span class="pre">B</span></code> defines a more intelligent <a class="reference internal" href="../reference/datamodel.html#object.__radd__" title="object.__radd__"><code class="xref py py-meth docutils literal"><span class="pre">__radd__()</span></code></a>, so the boilerplate should return <a class="reference internal" href="constants.html#NotImplemented" title="NotImplemented"><code class="xref py py-const docutils literal"><span class="pre">NotImplemented</span></code></a> from <a class="reference internal" href="../reference/datamodel.html#object.__add__" title="object.__add__"><code class="xref py py-meth docutils literal"><span class="pre">__add__()</span></code></a>. (Or <code class="docutils literal"><span class="pre">A</span></code> may not implement <a class="reference internal" href="../reference/datamodel.html#object.__add__" title="object.__add__"><code class="xref py py-meth docutils literal"><span class="pre">__add__()</span></code></a> at all.)</li> <li>Then <code class="docutils literal"><span class="pre">B</span></code>s <a class="reference internal" href="../reference/datamodel.html#object.__radd__" title="object.__radd__"><code class="xref py py-meth docutils literal"><span class="pre">__radd__()</span></code></a> gets a chance. If it accepts <code class="docutils literal"><span class="pre">a</span></code>, 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 <code class="docutils literal"><span class="pre">B</span> <span class="pre">&lt;:</span> <span class="pre">A</span></code>, Python tries <code class="docutils literal"><span class="pre">B.__radd__</span></code> before <code class="docutils literal"><span class="pre">A.__add__</span></code>. This is ok, because it was implemented with knowledge of <code class="docutils literal"><span class="pre">A</span></code>, so it can handle those instances before delegating to <a class="reference internal" href="#numbers.Complex" title="numbers.Complex"><code class="xref py py-class docutils literal"><span class="pre">Complex</span></code></a>.</li> </ol> </div></blockquote></span><p><span class="yiyi-st" id="yiyi-65">If <code class="docutils literal"><span class="pre">A</span> <span class="pre">&lt;:</span> <span class="pre">Complex</span></code> and <code class="docutils literal"><span class="pre">B</span> <span class="pre">&lt;:</span> <span class="pre">Real</span></code> without sharing any other knowledge, then the appropriate shared operation is the one involving the built in <a class="reference internal" href="functions.html#complex" title="complex"><code class="xref py py-class docutils literal"><span class="pre">complex</span></code></a>, and both <a class="reference internal" href="../reference/datamodel.html#object.__radd__" title="object.__radd__"><code class="xref py py-meth docutils literal"><span class="pre">__radd__()</span></code></a> s land there, so <code class="docutils literal"><span class="pre">a+b</span> <span class="pre">==</span> <span class="pre">b+a</span></code>.</span></p><p><span class="yiyi-st" id="yiyi-66">由于大多数任何给定类型操作会很相似,因此,它能定义可生成任何给定操作正反向实例的 helper 函数。</span><span class="yiyi-st" id="yiyi-67">例如,<a class="reference internal" href="fractions.html#fractions.Fraction" title="fractions.Fraction"><code class="xref py py-class docutils literal"><span class="pre">fractions.Fraction</span></code></a>使用:</span></p><pre><code class="language-python"><span></span><span class="k">def</span> <span class="nf">_operator_fallbacks</span><span class="p">(</span><span class="n">monomorphic_operator</span><span class="p">,</span> <span class="n">fallback_operator</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">forward</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="n">Fraction</span><span class="p">)):</span>
<span class="k">return</span> <span class="n">monomorphic_operator</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="nb">float</span><span class="p">):</span>
<span class="k">return</span> <span class="n">fallback_operator</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">a</span><span class="p">),</span> <span class="n">b</span><span class="p">)</span>
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="nb">complex</span><span class="p">):</span>
<span class="k">return</span> <span class="n">fallback_operator</span><span class="p">(</span><span class="nb">complex</span><span class="p">(</span><span class="n">a</span><span class="p">),</span> <span class="n">b</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="n">forward</span><span class="o">.</span><span class="n">__name__</span> <span class="o">=</span> <span class="s1">'__'</span> <span class="o">+</span> <span class="n">fallback_operator</span><span class="o">.</span><span class="n">__name__</span> <span class="o">+</span> <span class="s1">'__'</span>
<span class="n">forward</span><span class="o">.</span><span class="n">__doc__</span> <span class="o">=</span> <span class="n">monomorphic_operator</span><span class="o">.</span><span class="n">__doc__</span>
<span class="k">def</span> <span class="nf">reverse</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">a</span><span class="p">):</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">Rational</span><span class="p">):</span>
<span class="c1"># Includes ints.</span>
<span class="k">return</span> <span class="n">monomorphic_operator</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">numbers</span><span class="o">.</span><span class="n">Real</span><span class="p">):</span>
<span class="k">return</span> <span class="n">fallback_operator</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">a</span><span class="p">),</span> <span class="nb">float</span><span class="p">(</span><span class="n">b</span><span class="p">))</span>
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">numbers</span><span class="o">.</span><span class="n">Complex</span><span class="p">):</span>
<span class="k">return</span> <span class="n">fallback_operator</span><span class="p">(</span><span class="nb">complex</span><span class="p">(</span><span class="n">a</span><span class="p">),</span> <span class="nb">complex</span><span class="p">(</span><span class="n">b</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="n">reverse</span><span class="o">.</span><span class="n">__name__</span> <span class="o">=</span> <span class="s1">'__r'</span> <span class="o">+</span> <span class="n">fallback_operator</span><span class="o">.</span><span class="n">__name__</span> <span class="o">+</span> <span class="s1">'__'</span>
<span class="n">reverse</span><span class="o">.</span><span class="n">__doc__</span> <span class="o">=</span> <span class="n">monomorphic_operator</span><span class="o">.</span><span class="n">__doc__</span>
<span class="k">return</span> <span class="n">forward</span><span class="p">,</span> <span class="n">reverse</span>
<span class="k">def</span> <span class="nf">_add</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
<span class="sd">"""a + b"""</span>
<span class="k">return</span> <span class="n">Fraction</span><span class="p">(</span><span class="n">a</span><span class="o">.</span><span class="n">numerator</span> <span class="o">*</span> <span class="n">b</span><span class="o">.</span><span class="n">denominator</span> <span class="o">+</span>
<span class="n">b</span><span class="o">.</span><span class="n">numerator</span> <span class="o">*</span> <span class="n">a</span><span class="o">.</span><span class="n">denominator</span><span class="p">,</span>
<span class="n">a</span><span class="o">.</span><span class="n">denominator</span> <span class="o">*</span> <span class="n">b</span><span class="o">.</span><span class="n">denominator</span><span class="p">)</span>
<span class="n">__add__</span><span class="p">,</span> <span class="n">__radd__</span> <span class="o">=</span> <span class="n">_operator_fallbacks</span><span class="p">(</span><span class="n">_add</span><span class="p">,</span> <span class="n">operator</span><span class="o">.</span><span class="n">add</span><span class="p">)</span>
<span class="c1"># ...</span>
</code></pre></div></div></div></div>