FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Add numbers.py. I suspect this is an old version, but Jeffrey is out · python/cpython@1daf954 · GitHub

Repository navigation

Commit 1daf954

Browse files
committed
Add numbers.py. I suspect this is an old version, but Jeffrey is out
of town, and it will have to do for now.
1 parent 3cd6537 commit 1daf954

2 files changed

Lines changed: 378 additions & 0 deletions

File tree

‎Lib/numbers.py‎

Lines changed: 325 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,325 @@
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+
from abc import ABCMeta, abstractmethod, abstractproperty
7+
8+
__all__ = ["Number", "Exact", "Inexact",
9+
"Complex", "Real", "Rational", "Integral",
10+
]
11+
12+
13+
class Number(metaclass=ABCMeta):
14+
"""All numbers inherit from this class.
15+
16+
If you just want to check if an argument x is a number, without
17+
caring what kind, use isinstance(x, Number).
18+
"""
19+
20+
21+
class Exact(Number):
22+
"""Operations on instances of this type are exact.
23+
24+
As long as the result of a homogenous operation is of the same
25+
type, you can assume that it was computed exactly, and there are
26+
no round-off errors. Laws like commutativity and associativity
27+
hold.
28+
"""
29+
30+
Exact.register(int)
31+
32+
33+
class Inexact(Number):
34+
"""Operations on instances of this type are inexact.
35+
36+
Given X, an instance of Inexact, it is possible that (X + -X) + 3
37+
== 3, but X + (-X + 3) == 0. The exact form this error takes will
38+
vary by type, but it's generally unsafe to compare this type for
39+
equality.
40+
"""
41+
42+
Inexact.register(complex)
43+
Inexact.register(float)
44+
45+
46+
class Complex(Number):
47+
"""Complex defines the operations that work on the builtin complex type.
48+
49+
In short, those are: a conversion to complex, .real, .imag, +, -,
50+
*, /, abs(), .conjugate, ==, and !=.
51+
52+
If it is given heterogenous arguments, and doesn't have special
53+
knowledge about them, it should fall back to the builtin complex
54+
type as described below.
55+
"""
56+
57+
@abstractmethod
58+
def __complex__(self):
59+
"""Return a builtin complex instance."""
60+
61+
def __bool__(self):
62+
"""True if self != 0."""
63+
return self != 0
64+
65+
@abstractproperty
66+
def real(self):
67+
"""Retrieve the real component of this number.
68+
69+
This should subclass Real.
70+
"""
71+
raise NotImplementedError
72+
73+
@abstractproperty
74+
def imag(self):
75+
"""Retrieve the real component of this number.
76+
77+
This should subclass Real.
78+
"""
79+
raise NotImplementedError
80+
81+
@abstractmethod
82+
def __add__(self, other):
83+
raise NotImplementedError
84+
85+
@abstractmethod
86+
def __radd__(self, other):
87+
raise NotImplementedError
88+
89+
@abstractmethod
90+
def __neg__(self):
91+
raise NotImplementedError
92+
93+
def __pos__(self):
94+
return self
95+
96+
def __sub__(self, other):
97+
return self + -other
98+
99+
def __rsub__(self, other):
100+
return -self + other
101+
102+
@abstractmethod
103+
def __mul__(self, other):
104+
raise NotImplementedError
105+
106+
@abstractmethod
107+
def __rmul__(self, other):
108+
raise NotImplementedError
109+
110+
@abstractmethod
111+
def __div__(self, other):
112+
raise NotImplementedError
113+
114+
@abstractmethod
115+
def __rdiv__(self, other):
116+
raise NotImplementedError
117+
118+
@abstractmethod
119+
def __pow__(self, exponent):
120+
"""Like division, a**b should promote to complex when necessary."""
121+
raise NotImplementedError
122+
123+
@abstractmethod
124+
def __rpow__(self, base):
125+
raise NotImplementedError
126+
127+
@abstractmethod
128+
def __abs__(self):
129+
"""Returns the Real distance from 0."""
130+
raise NotImplementedError
131+
132+
@abstractmethod
133+
def conjugate(self):
134+
"""(x+y*i).conjugate() returns (x-y*i)."""
135+
raise NotImplementedError
136+
137+
@abstractmethod
138+
def __eq__(self, other):
139+
raise NotImplementedError
140+
141+
def __ne__(self, other):
142+
return not (self == other)
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+
@abstractmethod
157+
def __float__(self):
158+
"""Any Real can be converted to a native float object."""
159+
raise NotImplementedError
160+
161+
@abstractmethod
162+
def __trunc__(self):
163+
"""Truncates self to an Integral.
164+
165+
Returns an Integral i such that:
166+
* i>0 iff self>0
167+
* abs(i) <= abs(self).
168+
"""
169+
raise NotImplementedError
170+
171+
def __divmod__(self, other):
172+
"""The pair (self // other, self % other).
173+
174+
Sometimes this can be computed faster than the pair of
175+
operations.
176+
"""
177+
return (self // other, self % other)
178+
179+
def __rdivmod__(self, other):
180+
"""The pair (self // other, self % other).
181+
182+
Sometimes this can be computed faster than the pair of
183+
operations.
184+
"""
185+
return (other // self, other % self)
186+
187+
@abstractmethod
188+
def __floordiv__(self, other):
189+
"""The floor() of self/other."""
190+
raise NotImplementedError
191+
192+
@abstractmethod
193+
def __rfloordiv__(self, other):
194+
"""The floor() of other/self."""
195+
raise NotImplementedError
196+
197+
@abstractmethod
198+
def __mod__(self, other):
199+
raise NotImplementedError
200+
201+
@abstractmethod
202+
def __rmod__(self, other):
203+
raise NotImplementedError
204+
205+
@abstractmethod
206+
def __lt__(self, other):
207+
"""< on Reals defines a total ordering, except perhaps for NaN."""
208+
raise NotImplementedError
209+
210+
def __le__(self, other):
211+
raise NotImplementedError
212+
213+
# Concrete implementations of Complex abstract methods.
214+
def __complex__(self):
215+
return complex(float(self))
216+
217+
@property
218+
def real(self):
219+
return self
220+
221+
@property
222+
def imag(self):
223+
return 0
224+
225+
def conjugate(self):
226+
"""Conjugate is a no-op for Reals."""
227+
return self
228+
229+
Real.register(float)
230+
231+
232+
class Rational(Real, Exact):
233+
""".numerator and .denominator should be in lowest terms."""
234+
235+
@abstractproperty
236+
def numerator(self):
237+
raise NotImplementedError
238+
239+
@abstractproperty
240+
def denominator(self):
241+
raise NotImplementedError
242+
243+
# Concrete implementation of Real's conversion to float.
244+
def __float__(self):
245+
return self.numerator / self.denominator
246+
247+
248+
class Integral(Rational):
249+
"""Integral adds a conversion to int and the bit-string operations."""
250+
251+
@abstractmethod
252+
def __int__(self):
253+
raise NotImplementedError
254+
255+
def __index__(self):
256+
return int(self)
257+
258+
@abstractmethod
259+
def __pow__(self, exponent, modulus):
260+
"""self ** exponent % modulus, but maybe faster.
261+
262+
Implement this if you want to support the 3-argument version
263+
of pow(). Otherwise, just implement the 2-argument version
264+
described in Complex. Raise a TypeError if exponent < 0 or any
265+
argument isn't Integral.
266+
"""
267+
raise NotImplementedError
268+
269+
@abstractmethod
270+
def __lshift__(self, other):
271+
raise NotImplementedError
272+
273+
@abstractmethod
274+
def __rlshift__(self, other):
275+
raise NotImplementedError
276+
277+
@abstractmethod
278+
def __rshift__(self, other):
279+
raise NotImplementedError
280+
281+
@abstractmethod
282+
def __rrshift__(self, other):
283+
raise NotImplementedError
284+
285+
@abstractmethod
286+
def __and__(self, other):
287+
raise NotImplementedError
288+
289+
@abstractmethod
290+
def __rand__(self, other):
291+
raise NotImplementedError
292+
293+
@abstractmethod
294+
def __xor__(self, other):
295+
raise NotImplementedError
296+
297+
@abstractmethod
298+
def __rxor__(self, other):
299+
raise NotImplementedError
300+
301+
@abstractmethod
302+
def __or__(self, other):
303+
raise NotImplementedError
304+
305+
@abstractmethod
306+
def __ror__(self, other):
307+
raise NotImplementedError
308+
309+
@abstractmethod
310+
def __invert__(self):
311+
raise NotImplementedError
312+
313+
# Concrete implementations of Rational and Real abstract methods.
314+
def __float__(self):
315+
return float(int(self))
316+
317+
@property
318+
def numerator(self):
319+
return self
320+
321+
@property
322+
def denominator(self):
323+
return 1
324+
325+
Integral.register(int)

‎Lib/test/test_abstract_numbers.py‎

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
"""Unit tests for numbers.py."""
2+
3+
import unittest
4+
from test import test_support
5+
from numbers import Number
6+
from numbers import Exact, Inexact
7+
from numbers import Complex, Real, Rational, Integral
8+
import operator
9+
10+
class TestNumbers(unittest.TestCase):
11+
def test_int(self):
12+
self.failUnless(issubclass(int, Integral))
13+
self.failUnless(issubclass(int, Complex))
14+
self.failUnless(issubclass(int, Exact))
15+
self.failIf(issubclass(int, Inexact))
16+
17+
self.assertEqual(7, int(7).real)
18+
self.assertEqual(0, int(7).imag)
19+
self.assertEqual(7, int(7).conjugate())
20+
self.assertEqual(7, int(7).numerator)
21+
self.assertEqual(1, int(7).denominator)
22+
23+
def test_float(self):
24+
self.failIf(issubclass(float, Rational))
25+
self.failUnless(issubclass(float, Real))
26+
self.failIf(issubclass(float, Exact))
27+
self.failUnless(issubclass(float, Inexact))
28+
29+
self.assertEqual(7.3, float(7.3).real)
30+
self.assertEqual(0, float(7.3).imag)
31+
self.assertEqual(7.3, float(7.3).conjugate())
32+
33+
def test_complex(self):
34+
self.failIf(issubclass(complex, Real))
35+
self.failUnless(issubclass(complex, Complex))
36+
self.failIf(issubclass(complex, Exact))
37+
self.failUnless(issubclass(complex, Inexact))
38+
39+
c1, c2 = complex(3, 2), complex(4,1)
40+
# TODO: Uncomment this test when trunc() exists.
41+
#self.assertRaises(None, trunc, c1)
42+
self.assertRaises(TypeError, operator.mod, c1, c2)
43+
self.assertRaises(TypeError, divmod, c1, c2)
44+
self.assertRaises(TypeError, operator.floordiv, c1, c2)
45+
self.assertRaises(TypeError, float, c1)
46+
self.assertRaises(TypeError, int, c1)
47+
48+
def test_main():
49+
test_support.run_unittest(TestNumbers)
50+
51+
52+
if __name__ == "__main__":
53+
unittest.main()

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL