Hierarquia de Tipos Numéricos em Python

Este documento descreve a estrutura de classes abstratas para representar tipos numéricos na linguagem Python, conforme definido na PEP 3141. O sistema propõe uma hierarquia de herança onde cada nível representa propriedades matemáticas específicas, permitindo operações consistentes entre diferentes tipos numéricos.

A arquitetura central baseia-se na seguinte cadeia de herança: Numerico :> Complexo :> Real :> Racional :> Integral, onde A :> B indica que A é subclasse de B. Essa estrutura foi inspirada no "numeric tower" da linguagem Scheme.

Estrutura das Classes Abstratas

A classe raiz Numerico serve apenas como marcador para sobrecarga de funções:

class Numerico(metaclass=ABCMeta): 
    pass

A classe Complexo define operações para números complexos, incluindo métodos abstratos essenciais:

class Complexo(Numerico):
    @abstractmethod
    def para_complexo(self):
        """Converte para tipo complex nativo."""
        raise NotImplementedError

    @abstractproperty
    def real_parte(self):
        """Componente real do número (deve ser Real)."""
        raise NotImplementedError

    @abstractproperty
    def imaginario_parte(self):
        """Componente imaginário (deve ser Real)."""
        raise NotImplementedError

    @abstractmethod
    def __adicionar__(self, outro):
        raise NotImplementedError

    # Métodos omitidos para brevidade: __subtrair__, __multiplicar__, etc.

A classe Real estende Complexo adicionando operações específicas para números reais:

class Real(Complexo):
    @abstractmethod
    def para_float(self):
        """Conversão para tipo float nativo."""
        raise NotImplementedError

    @abstractmethod
    def truncar(self):
        """Retorna parte inteira sem arredondamento."""
        raise NotImplementedError

    @abstractmethod
    def arredondar(self, casas: Integral = None):
        """Arredonda para casas decimais especificadas."""
        raise NotImplementedError

A hierarquia continua com Racional para frações e Integral para números inteiros:

class Racional(Real):
    @abstractproperty
    def numerador(self):
        raise NotImplementedError

    @abstractproperty
    def denominador(self):
        raise NotImplementedError

class Integral(Racional):
    @abstractmethod
    def para_inteiro(self):
        raise NotImplementedError

    def operacao_bitwise_esquerda(self, outro):
        return self.para_inteiro() << outro.para_inteiro()

Implementação de Operações

Para operações mistas entre tipos diferentes, a implementação deve seguir padrões específicos. Exemplo de adição em uma subclasse de Integral:

class MeuInteiro(Integral):
    def __adicionar__(self, outro):
        if isinstance(outro, MeuInteiro):
            return calcular_soma(self, outro)
        elif isinstance(outro, TipoEspecial):
            return calcular_soma_especial(self, outro)
        return NotImplemented

    def __r_adicionar__(self, outro):
        if isinstance(outro, Integral):
            return outro.para_inteiro() + self.para_inteiro()
        elif isinstance(outro, Real):
            return outro.para_float() + float(self.para_inteiro())
        return NotImplemented

Considerações para Desenvolvedores

Ao implementar novos tipos numéricos:

  • Garanta que valores equivalentes tenham o mesmo hash
  • Utilize register() para adicionar classes intermediárias
  • Respeite a ordem de conversão: Entegral → Real → Complexo

Operações como trunc(), floor() e ceil() exigem implementações específicas em subclasses de Real, enquanto operações bitwise são exclusivas de Integral. O sistema permite que bibliotecas como NumPy definam tipos numéricos customizados compatíveis com a hierarquia padrão.

Tags: ABC tipos-abstratos pep3141 hierarquia-tipos metaclasses

Publicado em 10-1 08:24