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

バージョン 2.6 で追加.

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

class numbers.Number

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


9.1.1. 数値塔
=============

class numbers.Complex

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

   real

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

   imag

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

   conjugate()

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

class numbers.Real

   "Complex" の上に、 "Real" は実数で意味を成す演算を加えます。

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

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

class numbers.Rational

   "Real" をサブタイプ化し "numerator" と "denominator" のプロパティを
   加えたものです。これらは既約分数のものでなければなりません。この他
   に "float()" のデフォルトも提供します。

   numerator

      抽象プロパティ。

   denominator

      抽象プロパティ。

class numbers.Integral

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


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

実装する人は等しい数が等しく扱われるように同じハッシュを与えるように気
を付けねばなりません。これは二つの異なった実数の拡張があるような場合に
はややこしいことになるかもしれません。たとえば、 "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))


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

もちろん、他にも数に対する ABC が有り得ますし、そういったものを付け加
える可能性を閉ざしてしまうとすれば貧相な階層でしかありません。たとえば
"MyFoo" を "Complex" と "Real" の間に付け加えるには:

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


9.1.2.2. 算術演算の実装
-----------------------

私たちは、混在型(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, long, 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)

   # ...
