mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 21:51:50 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			390 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			390 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # 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, abstractproperty
 | |
| 
 | |
| __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 heterogenous 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
 | |
| 
 | |
|     @abstractproperty
 | |
|     def real(self):
 | |
|         """Retrieve the real component of this number.
 | |
| 
 | |
|         This should subclass Real.
 | |
|         """
 | |
|         raise NotImplementedError
 | |
| 
 | |
|     @abstractproperty
 | |
|     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
 | |
| 
 | |
|     def __ne__(self, other):
 | |
|         """self != other"""
 | |
|         # The default __ne__ doesn't negate __eq__ until 3.0.
 | |
|         return not (self == other)
 | |
| 
 | |
| 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 (self // other, self % other).
 | |
| 
 | |
|         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__ = ()
 | |
| 
 | |
|     @abstractproperty
 | |
|     def numerator(self):
 | |
|         raise NotImplementedError
 | |
| 
 | |
|     @abstractproperty
 | |
|     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 a conversion to int and the bit-string operations."""
 | |
| 
 | |
|     __slots__ = ()
 | |
| 
 | |
|     @abstractmethod
 | |
|     def __int__(self):
 | |
|         """int(self)"""
 | |
|         raise NotImplementedError
 | |
| 
 | |
|     def __index__(self):
 | |
|         """someobject[self]"""
 | |
|         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)
 | 
