Source code for numbers

  1# Copyright 2007 Google, Inc. All Rights Reserved.
  2# Licensed to PSF under a Contributor Agreement.
  3
  4"""Abstract Base Classes (ABCs) for numbers, according to PEP 3141.
  5
  6TODO: Fill out more detailed documentation on the operators."""
  7
  8############ Maintenance notes #########################################
  9#
 10# ABCs are different from other standard library modules in that they
 11# specify compliance tests.  In general, once an ABC has been published,
 12# new methods (either abstract or concrete) cannot be added.
 13#
 14# Though classes that inherit from an ABC would automatically receive a
 15# new mixin method, registered classes would become non-compliant and
 16# violate the contract promised by ``isinstance(someobj, SomeABC)``.
 17#
 18# Though irritating, the correct procedure for adding new abstract or
 19# mixin methods is to create a new ABC as a subclass of the previous
 20# ABC.
 21#
 22# Because they are so hard to change, new ABCs should have their APIs
 23# carefully thought through prior to publication.
 24#
 25# Since ABCMeta only checks for the presence of methods, it is possible
 26# to alter the signature of a method by adding optional arguments
 27# or changing parameter names.  This is still a bit dubious but at
 28# least it won't cause isinstance() to return an incorrect result.
 29#
 30#
 31#######################################################################
 32
 33from abc import ABCMeta, abstractmethod
 34
 35__all__ = ["Number", "Complex", "Real", "Rational", "Integral"]
 36
 37class Number(metaclass=ABCMeta):
 38    """All numbers inherit from this class.
 39
 40    If you just want to check if an argument x is a number, without
 41    caring what kind, use isinstance(x, Number).
 42    """
 43    __slots__ = ()
 44
 45    # Concrete numeric types must provide their own hash implementation
 46    __hash__ = None
 47
 48
 49## Notes on Decimal
 50## ----------------
 51## Decimal has all of the methods specified by the Real abc, but it should
 52## not be registered as a Real because decimals do not interoperate with
 53## binary floats (i.e.  Decimal('3.14') + 2.71828 is undefined).  But,
 54## abstract reals are expected to interoperate (i.e. R1 + R2 should be
 55## expected to work if R1 and R2 are both Reals).
 56
 57class Complex(Number):
 58    """Complex defines the operations that work on the builtin complex type.
 59
 60    In short, those are: a conversion to complex, .real, .imag, +, -,
 61    *, /, **, abs(), .conjugate, ==, and !=.
 62
 63    If it is given heterogeneous arguments, and doesn't have special
 64    knowledge about them, it should fall back to the builtin complex
 65    type as described below.
 66    """
 67
 68    __slots__ = ()
 69
 70    @abstractmethod
 71    def __complex__(self):
 72        """Return a builtin complex instance. Called for complex(self)."""
 73
 74    def __bool__(self):
 75        """True if self != 0. Called for bool(self)."""
 76        return self != 0
 77
 78    @property
 79    @abstractmethod
 80    def real(self):
 81        """Retrieve the real component of this number.
 82
 83        This should subclass Real.
 84        """
 85        raise NotImplementedError
 86
 87    @property
 88    @abstractmethod
 89    def imag(self):
 90        """Retrieve the imaginary component of this number.
 91
 92        This should subclass Real.
 93        """
 94        raise NotImplementedError
 95
 96    @abstractmethod
 97    def __add__(self, other):
 98        """self + other"""
 99        raise NotImplementedError
100
101    @abstractmethod
102    def __radd__(self, other):
103        """other + self"""
104        raise NotImplementedError
105
106    @abstractmethod
107    def __neg__(self):
108        """-self"""
109        raise NotImplementedError
110
111    @abstractmethod
112    def __pos__(self):
113        """+self"""
114        raise NotImplementedError
115
116    def __sub__(self, other):
117        """self - other"""
118        return self + -other
119
120    def __rsub__(self, other):
121        """other - self"""
122        return -self + other
123
124    @abstractmethod
125    def __mul__(self, other):
126        """self * other"""
127        raise NotImplementedError
128
129    @abstractmethod
130    def __rmul__(self, other):
131        """other * self"""
132        raise NotImplementedError
133
134    @abstractmethod
135    def __truediv__(self, other):
136        """self / other: Should promote to float when necessary."""
137        raise NotImplementedError
138
139    @abstractmethod
140    def __rtruediv__(self, other):
141        """other / self"""
142        raise NotImplementedError
143
144    @abstractmethod
145    def __pow__(self, exponent):
146        """self ** exponent; should promote to float or complex when necessary."""
147        raise NotImplementedError
148
149    @abstractmethod
150    def __rpow__(self, base):
151        """base ** self"""
152        raise NotImplementedError
153
154    @abstractmethod
155    def __abs__(self):
156        """Returns the Real distance from 0. Called for abs(self)."""
157        raise NotImplementedError
158
159    @abstractmethod
160    def conjugate(self):
161        """(x+y*i).conjugate() returns (x-y*i)."""
162        raise NotImplementedError
163
164    @abstractmethod
165    def __eq__(self, other):
166        """self == other"""
167        raise NotImplementedError
168
169Complex.register(complex)
170
171
[docs] 172class Real(Complex): 173 """To Complex, Real adds the operations that work on real numbers. 174 175 In short, those are: a conversion to float, trunc(), divmod, 176 %, <, <=, >, and >=. 177 178 Real also provides defaults for the derived operations. 179 """ 180 181 __slots__ = () 182 183 @abstractmethod 184 def __float__(self): 185 """Any Real can be converted to a native float object. 186 187 Called for float(self).""" 188 raise NotImplementedError 189 190 @abstractmethod 191 def __trunc__(self): 192 """trunc(self): Truncates self to an Integral. 193 194 Returns an Integral i such that: 195 * i > 0 iff self > 0; 196 * abs(i) <= abs(self); 197 * for any Integral j satisfying the first two conditions, 198 abs(i) >= abs(j) [i.e. i has "maximal" abs among those]. 199 i.e. "truncate towards 0". 200 """ 201 raise NotImplementedError 202 203 @abstractmethod 204 def __floor__(self): 205 """Finds the greatest Integral <= self.""" 206 raise NotImplementedError 207 208 @abstractmethod 209 def __ceil__(self): 210 """Finds the least Integral >= self.""" 211 raise NotImplementedError 212 213 @abstractmethod 214 def __round__(self, ndigits=None): 215 """Rounds self to ndigits decimal places, defaulting to 0. 216 217 If ndigits is omitted or None, returns an Integral, otherwise 218 returns a Real. Rounds half toward even. 219 """ 220 raise NotImplementedError 221 222 def __divmod__(self, other): 223 """divmod(self, other): The pair (self // other, self % other). 224 225 Sometimes this can be computed faster than the pair of 226 operations. 227 """ 228 return (self // other, self % other) 229 230 def __rdivmod__(self, other): 231 """divmod(other, self): The pair (other // self, other % self). 232 233 Sometimes this can be computed faster than the pair of 234 operations. 235 """ 236 return (other // self, other % self) 237 238 @abstractmethod 239 def __floordiv__(self, other): 240 """self // other: The floor() of self/other.""" 241 raise NotImplementedError 242 243 @abstractmethod 244 def __rfloordiv__(self, other): 245 """other // self: The floor() of other/self.""" 246 raise NotImplementedError 247 248 @abstractmethod 249 def __mod__(self, other): 250 """self % other""" 251 raise NotImplementedError 252 253 @abstractmethod 254 def __rmod__(self, other): 255 """other % self""" 256 raise NotImplementedError 257 258 @abstractmethod 259 def __lt__(self, other): 260 """self < other 261 262 < on Reals defines a total ordering, except perhaps for NaN.""" 263 raise NotImplementedError 264 265 @abstractmethod 266 def __le__(self, other): 267 """self <= other""" 268 raise NotImplementedError 269 270 # Concrete implementations of Complex abstract methods. 271 def __complex__(self): 272 """complex(self) == complex(float(self), 0)""" 273 return complex(float(self)) 274 275 @property 276 def real(self): 277 """Real numbers are their real component.""" 278 return +self 279 280 @property 281 def imag(self): 282 """Real numbers have no imaginary component.""" 283 return 0 284 285 def conjugate(self): 286 """Conjugate is a no-op for Reals.""" 287 return +self
288 289Real.register(float) 290 291 292class Rational(Real): 293 """.numerator and .denominator should be in lowest terms.""" 294 295 __slots__ = () 296 297 @property 298 @abstractmethod 299 def numerator(self): 300 raise NotImplementedError 301 302 @property 303 @abstractmethod 304 def denominator(self): 305 raise NotImplementedError 306 307 # Concrete implementation of Real's conversion to float. 308 def __float__(self): 309 """float(self) = self.numerator / self.denominator 310 311 It's important that this conversion use the integer's "true" 312 division rather than casting one side to float before dividing 313 so that ratios of huge integers convert without overflowing. 314 315 """ 316 return int(self.numerator) / int(self.denominator) 317 318 319class Integral(Rational): 320 """Integral adds methods that work on integral numbers. 321 322 In short, these are conversion to int, pow with modulus, and the 323 bit-string operations. 324 """ 325 326 __slots__ = () 327 328 @abstractmethod 329 def __int__(self): 330 """int(self)""" 331 raise NotImplementedError 332 333 def __index__(self): 334 """Called whenever an index is needed, such as in slicing""" 335 return int(self) 336 337 @abstractmethod 338 def __pow__(self, exponent, modulus=None): 339 """self ** exponent % modulus, but maybe faster. 340 341 Accept the modulus argument if you want to support the 342 3-argument version of pow(). Raise a TypeError if exponent < 0 343 or any argument isn't Integral. Otherwise, just implement the 344 2-argument version described in Complex. 345 """ 346 raise NotImplementedError 347 348 @abstractmethod 349 def __lshift__(self, other): 350 """self << other""" 351 raise NotImplementedError 352 353 @abstractmethod 354 def __rlshift__(self, other): 355 """other << self""" 356 raise NotImplementedError 357 358 @abstractmethod 359 def __rshift__(self, other): 360 """self >> other""" 361 raise NotImplementedError 362 363 @abstractmethod 364 def __rrshift__(self, other): 365 """other >> self""" 366 raise NotImplementedError 367 368 @abstractmethod 369 def __and__(self, other): 370 """self & other""" 371 raise NotImplementedError 372 373 @abstractmethod 374 def __rand__(self, other): 375 """other & self""" 376 raise NotImplementedError 377 378 @abstractmethod 379 def __xor__(self, other): 380 """self ^ other""" 381 raise NotImplementedError 382 383 @abstractmethod 384 def __rxor__(self, other): 385 """other ^ self""" 386 raise NotImplementedError 387 388 @abstractmethod 389 def __or__(self, other): 390 """self | other""" 391 raise NotImplementedError 392 393 @abstractmethod 394 def __ror__(self, other): 395 """other | self""" 396 raise NotImplementedError 397 398 @abstractmethod 399 def __invert__(self): 400 """~self""" 401 raise NotImplementedError 402 403 # Concrete implementations of Rational and Real abstract methods. 404 def __float__(self): 405 """float(self) == float(int(self))""" 406 return float(int(self)) 407 408 @property 409 def numerator(self): 410 """Integers are their own numerators.""" 411 return +self 412 413 @property 414 def denominator(self): 415 """Integers have a denominator of 1.""" 416 return 1 417 418Integral.register(int)