# 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."""
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).
# Concrete numeric types must provide their own hash implementation
## 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).
"""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 heterogenous arguments, and doesn't have special
knowledge about them, it should fall back to the builtin complex
"""Return a builtin complex instance. Called for complex(self)."""
"""True if self != 0. Called for bool(self)."""
"""Retrieve the real component of this number.
This should subclass Real.
raise NotImplementedError
"""Retrieve the imaginary component of this number.
This should subclass Real.
raise NotImplementedError
def __add__(self, other):
raise NotImplementedError
def __radd__(self, other):
raise NotImplementedError
raise NotImplementedError
raise NotImplementedError
def __sub__(self, other):
def __rsub__(self, other):
def __mul__(self, other):
raise NotImplementedError
def __rmul__(self, other):
raise NotImplementedError
def __truediv__(self, other):
"""self / other: Should promote to float when necessary."""
raise NotImplementedError
def __rtruediv__(self, other):
raise NotImplementedError
def __pow__(self, exponent):
"""self**exponent; should promote to float or complex when necessary."""
raise NotImplementedError
def __rpow__(self, base):
raise NotImplementedError
"""Returns the Real distance from 0. Called for abs(self)."""
raise NotImplementedError
"""(x+y*i).conjugate() returns (x-y*i)."""
raise NotImplementedError
raise NotImplementedError
Complex.register(complex)
"""To Complex, Real adds the operations that work on real numbers.
In short, those are: a conversion to float, trunc(), divmod,
Real also provides defaults for the derived operations.
"""Any Real can be converted to a native float object.
Called for float(self)."""
raise NotImplementedError
"""trunc(self): Truncates self to an Integral.
Returns an Integral i such that:
* 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
"""Finds the greatest Integral <= self."""
raise NotImplementedError
"""Finds the least Integral >= self."""
raise NotImplementedError
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
return (self // other, self % other)
def __rdivmod__(self, other):
"""divmod(other, self): The pair (self // other, self % other).
Sometimes this can be computed faster than the pair of
return (other // self, other % self)
def __floordiv__(self, other):
"""self // other: The floor() of self/other."""
raise NotImplementedError
def __rfloordiv__(self, other):
"""other // self: The floor() of other/self."""
raise NotImplementedError
def __mod__(self, other):
raise NotImplementedError
def __rmod__(self, other):
raise NotImplementedError
< on Reals defines a total ordering, except perhaps for NaN."""
raise NotImplementedError
raise NotImplementedError
# Concrete implementations of Complex abstract methods.
"""complex(self) == complex(float(self), 0)"""
return complex(float(self))
"""Real numbers are their real component."""
"""Real numbers have no imaginary component."""
"""Conjugate is a no-op for Reals."""
""".numerator and .denominator should be in lowest terms."""
raise NotImplementedError
raise NotImplementedError
# Concrete implementation of Real's conversion to float.
"""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 a conversion to int and the bit-string operations."""
raise NotImplementedError
"""Called whenever an index is needed, such as in slicing"""
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
def __lshift__(self, other):
raise NotImplementedError
def __rlshift__(self, other):
raise NotImplementedError
def __rshift__(self, other):
raise NotImplementedError
def __rrshift__(self, other):
raise NotImplementedError
def __and__(self, other):
raise NotImplementedError
def __rand__(self, other):
raise NotImplementedError
def __xor__(self, other):
raise NotImplementedError
def __rxor__(self, other):
raise NotImplementedError
raise NotImplementedError
def __ror__(self, other):
raise NotImplementedError
raise NotImplementedError
# Concrete implementations of Rational and Real abstract methods.
"""float(self) == float(int(self))"""
"""Integers are their own numerators."""
"""Integers have a denominator of 1."""