9.1. "numbers" --- Classes base abstratas numéricas
***************************************************

**Código Fonte:** 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 can be instantiated.

class numbers.Number

   A raiz da hierarquia numérica. Se você quiser apenas verificar se
   um argumento *x* é um número, sem se importar com o tipo, use
   "isinstance(x, Number)".


9.1.1. A torre numérica
=======================

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

      Abstrata. Obtém o componente real deste número.

   imag

      Abstrata. Obtém o componente imaginário deste número.

   abstractmethod conjugate()

      Abstrata. Retorna o conjugado complexo. Por exemplo,
      "(1+3j).conjugate() == (1-3j)".

class numbers.Real

   Para "Complex", "Real" adiciona as operações que funcionam em
   números reais.

   Em suma, são: uma conversão para "float", "math.trunc()",
   "round()", "math.floor()", "math.ceil()", "divmod()", "//", "%",
   "<", "<=", ">" e ">=".

   Real também fornece padrão para "complex()", "real", "imag" e
   "conjugate()".

class numbers.Rational

   Estende "Real" e adiciona as propriedades "numerator" e
   "denominator", que devem estar nos termos mais baixos. Com eles,
   ele fornece um padrão para "float()".

   numerator

      Abstrato.

   denominator

      Abstrato.

class numbers.Integral

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


9.1.2. Nota para implementadores de tipos
=========================================

Os implementadores devem ter o cuidado de tornar iguais números iguais
e fazer hash deles com os mesmos valores. Isso pode ser sutil se
houver duas extensões diferentes dos números reais. Por exemplo,
"fractions.Fraction" implementa "hash()" desta forma:

   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. Adicionando mais ABCs numéricas
----------------------------------------

Existem, é claro, mais ABCs possíveis para números, e isso seria uma
hierarquia pobre se excluísse a possibilidade de adicioná-los. Você
pode adicionar "MyFoo" entre "Complex" e "Real" com:

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


9.1.2.2. Implementando as operações aritméticas
-----------------------------------------------

Queremos implementar as operações aritméticas de forma que as
operações de modo misto chamem uma implementação cujo autor conhecia
os tipos de ambos os argumentos ou convertam ambos para o tipo
embutido mais próximo e façam a operação lá. Para subtipos de
"Integral", isso significa que "__add__()" e "__radd__()" devem ser
definidos com:

   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

Existem 5 casos diferentes para uma operação de tipo misto em
subclasses de "Complex". Vou me referir a todo o código acima que não
se refere a "MyIntegral" e "OtherTypeIKnowAbout" com um "modelo". "a"
será uma instância de "A", que é um subtipo de "Complex" ("a : A <:
Complex") e "b : B <: Complex". Vou considerar "a + b":

   1. Se "A" define um "__add__()", que aceita "b", tudo está bem.

   2. Se "A" voltar ao código padrão e tivesse que retornar um valor
      de "__add__()", perderíamos a possibilidade de que "B" definisse
      um "__radd__()" mais inteligente, então o código padrão deve
      retornar "NotImplemented" de "__add__()". (Ou "A" pode não
      implementar "__add__()".)

   3. Então, "__radd__()" do "B" consegue uma chance. Se ele aceitar
      "a", está tudo bem.

   4. Se ele recorrer ao padrão, não há mais métodos possíveis para
      tentar, então é aqui que a implementação padrão deve residir.

   5. Se "B <: A", Python tenta "B.__radd__" antes de "A.__add__".
      Isso está ok, porque foi implementado com conhecimento de "A",
      então ele pode lidar com essas instâncias antes de delegar para
      "Complex".

Se "A <: Complex" e "B <: Real" sem compartilhar nenhum outro
conhecimento, então a operação compartilhada apropriada é aquela
envolvendo a "complex" embutida, e ambos "__radd__()" s chegam lá, de
forma que "a+b == b+a".

Como a maioria das operações em qualquer tipo será muito semelhante,
pode ser útil definir uma função auxiliar que gera as instâncias de
avanço e reversão de qualquer operador. Por exemplo,
"fractions.Fraction" usa:

   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)

   # ...
