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