Skip to content
Snippets Groups Projects
Select Git revision
  • 7e46ae33bd522cf8331052c3c8835f9366599d8d
  • main default protected
  • 3.10
  • 3.11
  • revert-15688-bpo-38031-_io-FileIO-opener-crash
  • 3.8
  • 3.9
  • 3.7
  • enum-fix_auto
  • branch-v3.11.0
  • backport-c3648f4-3.11
  • gh-93963/remove-importlib-resources-abcs
  • refactor-wait_for
  • shared-testcase
  • v3.12.0a2
  • v3.12.0a1
  • v3.11.0
  • v3.8.15
  • v3.9.15
  • v3.10.8
  • v3.7.15
  • v3.11.0rc2
  • v3.8.14
  • v3.9.14
  • v3.7.14
  • v3.10.7
  • v3.11.0rc1
  • v3.10.6
  • v3.11.0b5
  • v3.11.0b4
  • v3.10.5
  • v3.11.0b3
  • v3.11.0b2
  • v3.9.13
34 results

numbers.py

Blame
  • numbers.py 11.19 KiB
    # Copyright 2007 Google, Inc. All Rights Reserved.
    # Licensed to PSF under a Contributor Agreement.
    
    """Abstract Base Classes (ABCs) for numbers, according to PEP 3141.
    
    TODO: Fill out more detailed documentation on the operators."""
    
    ############ Maintenance notes #########################################
    #
    # ABCs are different from other standard library modules in that they
    # specify compliance tests.  In general, once an ABC has been published,
    # new methods (either abstract or concrete) cannot be added.
    #
    # Though classes that inherit from an ABC would automatically receive a
    # new mixin method, registered classes would become non-compliant and
    # violate the contract promised by ``isinstance(someobj, SomeABC)``.
    #
    # Though irritating, the correct procedure for adding new abstract or
    # mixin methods is to create a new ABC as a subclass of the previous
    # ABC.
    #
    # Because they are so hard to change, new ABCs should have their APIs
    # carefully thought through prior to publication.
    #
    # Since ABCMeta only checks for the presence of methods, it is possible
    # to alter the signature of a method by adding optional arguments
    # or changing parameter names.  This is still a bit dubious but at
    # least it won't cause isinstance() to return an incorrect result.
    #
    #
    #######################################################################
    
    from abc import ABCMeta, abstractmethod
    
    __all__ = ["Number", "Complex", "Real", "Rational", "Integral"]
    
    class Number(metaclass=ABCMeta):
        """All numbers inherit from this class.
    
        If you just want to check if an argument x is a number, without
        caring what kind, use isinstance(x, Number).
        """
        __slots__ = ()
    
        # Concrete numeric types must provide their own hash implementation
        __hash__ = None
    
    
    ## Notes on Decimal
    ## ----------------
    ## Decimal has all of the methods specified by the Real abc, but it should
    ## not be registered as a Real because decimals do not interoperate with
    ## binary floats (i.e.  Decimal('3.14') + 2.71828 is undefined).  But,
    ## abstract reals are expected to interoperate (i.e. R1 + R2 should be
    ## expected to work if R1 and R2 are both Reals).
    
    class Complex(Number):
        """Complex defines the operations that work on the builtin complex type.
    
        In short, those are: a conversion to complex, .real, .imag, +, -,
        *, /, **, abs(), .conjugate, ==, and !=.
    
        If it is given heterogeneous arguments, and doesn't have special
        knowledge about them, it should fall back to the builtin complex
        type as described below.
        """
    
        __slots__ = ()
    
        @abstractmethod
        def __complex__(self):
            """Return a builtin complex instance. Called for complex(self)."""
    
        def __bool__(self):
            """True if self != 0. Called for bool(self)."""
            return self != 0
    
        @property
        @abstractmethod
        def real(self):
            """Retrieve the real component of this number.
    
            This should subclass Real.
            """
            raise NotImplementedError
    
        @property
        @abstractmethod
        def imag(self):
            """Retrieve the imaginary component of this number.
    
            This should subclass Real.
            """
            raise NotImplementedError
    
        @abstractmethod
        def __add__(self, other):
            """self + other"""
            raise NotImplementedError
    
        @abstractmethod
        def __radd__(self, other):
            """other + self"""
            raise NotImplementedError
    
        @abstractmethod
        def __neg__(self):
            """-self"""
            raise NotImplementedError
    
        @abstractmethod
        def __pos__(self):
            """+self"""
            raise NotImplementedError
    
        def __sub__(self, other):
            """self - other"""
            return self + -other
    
        def __rsub__(self, other):
            """other - self"""
            return -self + other
    
        @abstractmethod
        def __mul__(self, other):
            """self * other"""
            raise NotImplementedError
    
        @abstractmethod
        def __rmul__(self, other):
            """other * self"""
            raise NotImplementedError
    
        @abstractmethod
        def __truediv__(self, other):
            """self / other: Should promote to float when necessary."""
            raise NotImplementedError
    
        @abstractmethod
        def __rtruediv__(self, other):
            """other / self"""
            raise NotImplementedError
    
        @abstractmethod
        def __pow__(self, exponent):
            """self ** exponent; should promote to float or complex when necessary."""
            raise NotImplementedError
    
        @abstractmethod
        def __rpow__(self, base):
            """base ** self"""
            raise NotImplementedError
    
        @abstractmethod
        def __abs__(self):
            """Returns the Real distance from 0. Called for abs(self)."""
            raise NotImplementedError
    
        @abstractmethod
        def conjugate(self):
            """(x+y*i).conjugate() returns (x-y*i)."""
            raise NotImplementedError
    
        @abstractmethod
        def __eq__(self, other):
            """self == other"""
            raise NotImplementedError
    
    Complex.register(complex)
    
    
    class Real(Complex):
        """To Complex, Real adds the operations that work on real numbers.
    
        In short, those are: a conversion to float, trunc(), divmod,
        %, <, <=, >, and >=.
    
        Real also provides defaults for the derived operations.
        """
    
        __slots__ = ()
    
        @abstractmethod
        def __float__(self):
            """Any Real can be converted to a native float object.
    
            Called for float(self)."""
            raise NotImplementedError
    
        @abstractmethod
        def __trunc__(self):
            """trunc(self): Truncates self to an Integral.
    
            Returns an Integral i such that:
              * i > 0 iff self > 0;
              * abs(i) <= abs(self);
              * for any Integral j satisfying the first two conditions,
                abs(i) >= abs(j) [i.e. i has "maximal" abs among those].
            i.e. "truncate towards 0".
            """
            raise NotImplementedError
    
        @abstractmethod
        def __floor__(self):
            """Finds the greatest Integral <= self."""
            raise NotImplementedError
    
        @abstractmethod
        def __ceil__(self):
            """Finds the least Integral >= self."""
            raise NotImplementedError
    
        @abstractmethod
        def __round__(self, ndigits=None):
            """Rounds self to ndigits decimal places, defaulting to 0.
    
            If ndigits is omitted or None, returns an Integral, otherwise
            returns a Real. Rounds half toward even.
            """
            raise NotImplementedError
    
        def __divmod__(self, other):
            """divmod(self, other): The pair (self // other, self % other).
    
            Sometimes this can be computed faster than the pair of
            operations.
            """
            return (self // other, self % other)
    
        def __rdivmod__(self, other):
            """divmod(other, self): The pair (other // self, other % self).
    
            Sometimes this can be computed faster than the pair of
            operations.
            """
            return (other // self, other % self)
    
        @abstractmethod
        def __floordiv__(self, other):
            """self // other: The floor() of self/other."""
            raise NotImplementedError
    
        @abstractmethod
        def __rfloordiv__(self, other):
            """other // self: The floor() of other/self."""
            raise NotImplementedError
    
        @abstractmethod
        def __mod__(self, other):
            """self % other"""
            raise NotImplementedError
    
        @abstractmethod
        def __rmod__(self, other):
            """other % self"""
            raise NotImplementedError
    
        @abstractmethod
        def __lt__(self, other):
            """self < other
    
            < on Reals defines a total ordering, except perhaps for NaN."""
            raise NotImplementedError
    
        @abstractmethod
        def __le__(self, other):
            """self <= other"""
            raise NotImplementedError
    
        # Concrete implementations of Complex abstract methods.
        def __complex__(self):
            """complex(self) == complex(float(self), 0)"""
            return complex(float(self))
    
        @property
        def real(self):
            """Real numbers are their real component."""
            return +self
    
        @property
        def imag(self):
            """Real numbers have no imaginary component."""
            return 0
    
        def conjugate(self):
            """Conjugate is a no-op for Reals."""
            return +self
    
    Real.register(float)
    
    
    class Rational(Real):
        """.numerator and .denominator should be in lowest terms."""
    
        __slots__ = ()
    
        @property
        @abstractmethod
        def numerator(self):
            raise NotImplementedError
    
        @property
        @abstractmethod
        def denominator(self):
            raise NotImplementedError
    
        # Concrete implementation of Real's conversion to float.
        def __float__(self):
            """float(self) = self.numerator / self.denominator
    
            It's important that this conversion use the integer's "true"
            division rather than casting one side to float before dividing
            so that ratios of huge integers convert without overflowing.
    
            """
            return self.numerator / self.denominator
    
    
    class Integral(Rational):
        """Integral adds methods that work on integral numbers.
    
        In short, these are conversion to int, pow with modulus, and the
        bit-string operations.
        """
    
        __slots__ = ()
    
        @abstractmethod
        def __int__(self):
            """int(self)"""
            raise NotImplementedError
    
        def __index__(self):
            """Called whenever an index is needed, such as in slicing"""
            return int(self)
    
        @abstractmethod
        def __pow__(self, exponent, modulus=None):
            """self ** exponent % modulus, but maybe faster.
    
            Accept the modulus argument if you want to support the
            3-argument version of pow(). Raise a TypeError if exponent < 0
            or any argument isn't Integral. Otherwise, just implement the
            2-argument version described in Complex.
            """
            raise NotImplementedError
    
        @abstractmethod
        def __lshift__(self, other):
            """self << other"""
            raise NotImplementedError
    
        @abstractmethod
        def __rlshift__(self, other):
            """other << self"""
            raise NotImplementedError
    
        @abstractmethod
        def __rshift__(self, other):
            """self >> other"""
            raise NotImplementedError
    
        @abstractmethod
        def __rrshift__(self, other):
            """other >> self"""
            raise NotImplementedError
    
        @abstractmethod
        def __and__(self, other):
            """self & other"""
            raise NotImplementedError
    
        @abstractmethod
        def __rand__(self, other):
            """other & self"""
            raise NotImplementedError
    
        @abstractmethod
        def __xor__(self, other):
            """self ^ other"""
            raise NotImplementedError
    
        @abstractmethod
        def __rxor__(self, other):
            """other ^ self"""
            raise NotImplementedError
    
        @abstractmethod
        def __or__(self, other):
            """self | other"""
            raise NotImplementedError
    
        @abstractmethod
        def __ror__(self, other):
            """other | self"""
            raise NotImplementedError
    
        @abstractmethod
        def __invert__(self):
            """~self"""
            raise NotImplementedError
    
        # Concrete implementations of Rational and Real abstract methods.
        def __float__(self):
            """float(self) == float(int(self))"""
            return float(int(self))
    
        @property
        def numerator(self):
            """Integers are their own numerators."""
            return +self
    
        @property
        def denominator(self):
            """Integers have a denominator of 1."""
            return 1
    
    Integral.register(int)