"numbers" --- 숫자 추상 베이스 클래스
*************************************

**소스 코드:** Lib/numbers.py

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

The "numbers" module (**PEP 3141**) defines a hierarchy of numeric
*abstract base classes* which progressively define more operations.
None of the types defined in this module are intended to be
instantiated.

class numbers.Number

   숫자 계층의 최상위 클래스입니다. 형에 상관없이 인자 *x* 가 숫자인지
   확인하려면 "isinstance(x, Number)" 를 사용하세요.


숫자 계층
=========

class numbers.Complex

   Subclasses of this type describe complex numbers and include the
   operations that work on the built-in "complex" type. These are:
   conversions to "complex" and "bool", "real", "imag", "+", "-", "*",
   "/", "**", "abs()", "conjugate()", "==", and "!=". All except "-"
   and "!=" are abstract.

   real

      추상. 복소수의 실수부를 반환합니다.

   imag

      추상. 복소수의 허수부를 반환합니다.

   abstractmethod conjugate()

      추상 메서드. 켤레 복소수를 반환합니다. 예를 들어
      "(1+3j).conjugate() == (1-3j)" 입니다.

class numbers.Real

   "Real" 클래스는 "Complex" 클래스에 실수 연산을 추가합니다.

   요약하면 "float" 로의 변환과 "math.trunc()", "round()",
   "math.floor()", "math.ceil()", "divmod()", "//", "%", "<", "<=",
   ">", ">=" 가 포함됩니다.

   이 클래스는 또한 "complex()", "real", "imag", "conjugate()" 를 위한
   기본값을 제공합니다.

class numbers.Rational

   "Real" 의 하위 형이고 "numerator" 와 "denominator" 프로퍼티가 추가
   됩니다. 이 프로퍼티는 기약 분수의 값이어야 합니다. 또한 "float()"
   함수를 위한 기본값으로 사용됩니다.

   numerator

      프로퍼티(추상 메서드)

   denominator

      프로퍼티(추상 메서드)

class numbers.Integral

   Subtypes "Rational" and adds a conversion to "int".  Provides
   defaults for "float()", "numerator", and "denominator".  Adds
   abstract methods for "pow()" with modulus and bit-string
   operations: "<<", ">>", "&", "^", "|", "~".


형 구현을 위한 주의 사항
========================

구현자는 동일한 숫자가 같게 취급되고 같은 값으로 해싱되도록 해야 합니
다. 만약 종류가 다른 실수의 하위 형이 있는 경우 조금 까다로울 수 있습
니다. 예를 들어 "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를 추가하는 것이 가능합니다. 그렇지 않으면 엉망으
로 상속 계층이 구현될 것입니다. "Complex" 와 "Real" 사이에 다음과 같이
"MyFoo" 를 추가할 수 있습니다:

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


산술 연산 구현
--------------

다른 형에 대한 연산은 두 인자의 형에 관해 알고 있는 구현을 호출하거나
두 인자를 가장 비슷한 내장형으로 변환하여 연산하도록 산술 연산을 구현
하는 것이 좋습니다. "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

"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" 라면 파이썬은 "A.__add__" 메서드 전에 "B.__radd__"
      를 시도합니다. "A" 에 대해서 알고 "B" 가 구현되었기 때문에 이런
      행동은 문제없습니다. 따라서 "Complex" 에 위임하기 전에 이 인스턴
      스를 처리할 수 있습니다.

만약 어떤 것도 공유하지 않는 "A <: Complex" 와 "B <: Real" 라면 적절한
공유 연산(shared operation)은 내장 "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)

   # ...
