"numbers" --- 数の抽象基底クラス
********************************

**ソースコード:** Lib/numbers.py

======================================================================

"numbers" モジュール (**PEP 3141**) は数の *抽象基底クラス* の階層を定
義します。この階層では、さらに多くの演算が順番に定義されます。このモジ
ュールで定義される型はどれもインスタンス化を想定していません。

class numbers.Number

   数の階層の根。引数 *x* が、種類は何であれ、数であるということだけチ
   ェックしたい場合、"isinstance(x, Number)" が使えます。


数値塔
======

class numbers.Complex

   この型のサブクラスは複素数を表し、組み込みの "complex" 型を受け付け
   る演算を含みます。それらは: "complex" および "bool" への変換、
   "real", "imag", "+", "-", "*", "/", "**", "abs()", "conjugate()",
   "==", "!=" です。 "-" と "!=" 以外の全てのものは抽象メソッドや抽象
   プロパティです。

   real

      抽象プロパティ。この数の実部を取り出します。

   imag

      抽象プロパティ。この数の虚部を取り出します。

   abstractmethod conjugate()

      抽象プロパティ。複素共役を返します。たとえば、
      "(1+3j).conjugate() == (1-3j)" です。

class numbers.Real

   "Real" は、"Complex" 上に、 実数に対して行える演算を加えます。

   簡潔に言うとそれらは: "float" への変換, "math.trunc()", "round()",
   "math.floor()", "math.ceil()", "divmod()", "//", "%", "<", "<=",
   ">" および ">=" です。

   Real はまた "complex()", "real", "imag" および "conjugate()" のデフ
   ォルトを提供します。

class numbers.Rational

   "Real" をサブタイプ化し "numerator" と "denominator" のプロパティを
   加えたものです。これは "float()" のデフォルトも提供します。

   The "numerator" and "denominator" values should be instances of
   "Integral" and should be in lowest terms with "denominator"
   positive.

   numerator

      抽象プロパティ。

   denominator

      抽象プロパティ。

class numbers.Integral

   "Rational" をサブタイプ化し "int" への変換が加わります。 "float()",
   "numerator", "denominator" のデフォルトを提供します。法 (訳注: 割る
   数、除数のこと) を持つ "pow()" に対する抽象メソッドと、ビット列演算
   "<<", ">>", "&", "^", "|", "~" を追加します。


型実装者のための注意事項
========================

実装する人は等しい数が等しく扱われるように同じハッシュを与えるように気
を付けねばなりません。これは二つの異なった実数の拡張があるような場合に
はややこしいことになるかもしれません。たとえば、 "fractions.Fraction"
は "hash()" を以下のように実装しています:

   def __hash__(self):
       if self.denominator == 1:
           # Get integers right.
           return hash(self.numerator)
       # Expensive check, but definitely correct.
       if self == float(self):
           return hash(float(self))
       else:
           # Use tuple's hash to avoid a high collision rate on
           # simple fractions.
           return hash((self.numerator, self.denominator))


さらに数のABCを追加する
-----------------------

数に対する ABC が他にも多く存在しうることは、言うまでもありません。そ
れらの ABC を階層に追加する可能性が閉ざされるとしたら、その階層は貧相
な階層でしかありません。たとえば、 "MyFoo" を "Complex" と "Real" の間
に付け加えるには、次のようにします:

   class MyFoo(Complex): ...
   MyFoo.register(Real)


算術演算の実装
--------------

算術演算を実装する際には、型混合(mixed-mode)演算を行うと、作者が両方の
引数の型について知っているような実装を呼び出すか、両方の引数をそれぞれ
最も似ている組み込み型に変換してその型で演算を行うか、どちらになるのが
望ましい実装です。つまり、 "Integral" のサブタイプに対しては
"__add__()" と "__radd__()" を次のように定義するべきです:

   class MyIntegral(Integral):

       def __add__(self, other):
           if isinstance(other, MyIntegral):
               return do_my_adding_stuff(self, other)
           elif isinstance(other, OtherTypeIKnowAbout):
               return do_my_other_adding_stuff(self, other)
           else:
               return NotImplemented

       def __radd__(self, other):
           if isinstance(other, MyIntegral):
               return do_my_adding_stuff(other, self)
           elif isinstance(other, OtherTypeIKnowAbout):
               return do_my_other_adding_stuff(other, self)
           elif isinstance(other, Integral):
               return int(other) + int(self)
           elif isinstance(other, Real):
               return float(other) + float(self)
           elif isinstance(other, Complex):
               return complex(other) + complex(self)
           else:
               return NotImplemented

ここには5つの異なる "Complex" のサブクラス間の混在型の演算があります。
上のコードの中で "MyIntegral" と "OtherTypeIKnowAbout" に触れない部分
を "ボイラープレート" と呼ぶことにしましょう。 "a" を "Complex" のサブ
タイプである "A" のインスタンス ("a : A <: Complex")、同様に "b : B <:
Complex" として、 "a + b" を考えます:

   1. "A" が "b" を受け付ける "__add__()" を定義している場合、何も問題
      はありません。

   2. "A" でボイラープレート部分に落ち込み、その結果 "__add__()" が値
      を返すならば、 "B" に良く考えられた "__radd__()" が定義されてい
      る可能性を見逃してしまいますので、ボイラープレートは "__add__()"
      から "NotImplemented" を返すのが良いでしょう。(若しくは、 "A" は
      まったく "__add__()" を実装すべきではなかったかもしれません。)

   3. そうすると、 "B" の "__radd__()" にチャンスが巡ってきます。ここ
      で "a" が受け付けられるならば、結果は上々です。

   4. ここでボイラープレートに落ち込むならば、もう他に試すべきメソッド
      はありませんので、デフォルト実装の出番です。

   5. もし "B <: A" ならば、Python は "A.__add__" の前に "B.__radd__"
      を試します。これで良い理由は、 "A" についての知識を持って実装し
      ており、 "Complex" に委ねる前にこれらのインスタンスを扱えるはず
      だからです。

もし "A <: Complex" かつ "B <: Real" で他に共有された知識が無いならば
、適切な共通の演算は組み込みの "complex" を使ったものになり、どちらの
"__radd__()" ともそこに着地するでしょうから、 "a+b == b+a" です。

ほとんどの演算はどのような型についても非常に良く似ていますので、与えら
れた演算子について順結合(forward)および逆結合(reverse)のメソッドを生成
する支援関数を定義することは役に立ちます。たとえば、
"fractions.Fraction" では次のようなものを利用しています:

   def _operator_fallbacks(monomorphic_operator, fallback_operator):
       def forward(a, b):
           if isinstance(b, (int, Fraction)):
               return monomorphic_operator(a, b)
           elif isinstance(b, float):
               return fallback_operator(float(a), b)
           elif isinstance(b, complex):
               return fallback_operator(complex(a), b)
           else:
               return NotImplemented
       forward.__name__ = '__' + fallback_operator.__name__ + '__'
       forward.__doc__ = monomorphic_operator.__doc__

       def reverse(b, a):
           if isinstance(a, Rational):
               # Includes ints.
               return monomorphic_operator(a, b)
           elif isinstance(a, numbers.Real):
               return fallback_operator(float(a), float(b))
           elif isinstance(a, numbers.Complex):
               return fallback_operator(complex(a), complex(b))
           else:
               return NotImplemented
       reverse.__name__ = '__r' + fallback_operator.__name__ + '__'
       reverse.__doc__ = monomorphic_operator.__doc__

       return forward, reverse

   def _add(a, b):
       """a + b"""
       return Fraction(a.numerator * b.denominator +
                       b.numerator * a.denominator,
                       a.denominator * b.denominator)

   __add__, __radd__ = _operator_fallbacks(_add, operator.add)

   # ...
