blob: d78595e76da398ba7787ac0368e5418889798f39 [file] [log] [blame]
Christian Heimes072c0f12008-01-03 23:01:04 +00001:mod:`numbers` --- Numeric abstract base classes
2================================================
3
4.. module:: numbers
5 :synopsis: Numeric abstract base classes (Complex, Real, Integral, etc.).
6
Christian Heimesfaf2f632008-01-06 16:59:19 +00007
Christian Heimes072c0f12008-01-03 23:01:04 +00008The :mod:`numbers` module (:pep:`3141`) defines a hierarchy of numeric abstract
9base classes which progressively define more operations. These concepts also
10provide a way to distinguish exact from inexact types. None of the types defined
11in this module can be instantiated.
12
13
14.. class:: Number
15
16 The root of the numeric hierarchy. If you just want to check if an argument
17 *x* is a number, without caring what kind, use ``isinstance(x, Number)``.
18
19
20Exact and inexact operations
21----------------------------
22
23.. class:: Exact
24
25 Subclasses of this type have exact operations.
26
27 As long as the result of a homogenous operation is of the same type, you can
28 assume that it was computed exactly, and there are no round-off errors. Laws
29 like commutativity and associativity hold.
30
31
32.. class:: Inexact
33
34 Subclasses of this type have inexact operations.
35
36 Given X, an instance of :class:`Inexact`, it is possible that ``(X + -X) + 3
37 == 3``, but ``X + (-X + 3) == 0``. The exact form this error takes will vary
38 by type, but it's generally unsafe to compare this type for equality.
39
40
41The numeric tower
42-----------------
43
44.. class:: Complex
45
46 Subclasses of this type describe complex numbers and include the operations
47 that work on the builtin :class:`complex` type. These are: conversions to
48 :class:`complex` and :class:`bool`, :attr:`.real`, :attr:`.imag`, ``+``,
49 ``-``, ``*``, ``/``, :func:`abs`, :meth:`conjugate`, ``==``, and ``!=``. All
50 except ``-`` and ``!=`` are abstract.
51
52.. attribute:: Complex.real
53
54 Abstract. Retrieves the :class:`Real` component of this number.
55
56.. attribute:: Complex.imag
57
58 Abstract. Retrieves the :class:`Real` component of this number.
59
60.. method:: Complex.conjugate()
61
62 Abstract. Returns the complex conjugate. For example, ``(1+3j).conjugate() ==
63 (1-3j)``.
64
65.. class:: Real
66
67 To :class:`Complex`, :class:`Real` adds the operations that work on real
68 numbers.
69
70 In short, those are: a conversion to :class:`float`, :func:`trunc`,
71 :func:`round`, :func:`math.floor`, :func:`math.ceil`, :func:`divmod`, ``//``,
72 ``%``, ``<``, ``<=``, ``>``, and ``>=``.
73
74 Real also provides defaults for :func:`complex`, :attr:`Complex.real`,
75 :attr:`Complex.imag`, and :meth:`Complex.conjugate`.
76
77
78.. class:: Rational
79
80 Subtypes both :class:`Real` and :class:`Exact`, and adds
81 :attr:`Rational.numerator` and :attr:`Rational.denominator` properties, which
82 should be in lowest terms. With these, it provides a default for
83 :func:`float`.
84
85.. attribute:: Rational.numerator
86
87 Abstract.
88
89.. attribute:: Rational.denominator
90
91 Abstract.
92
93
94.. class:: Integral
95
96 Subtypes :class:`Rational` and adds a conversion to :class:`long`, the
97 3-argument form of :func:`pow`, and the bit-string operations: ``<<``,
98 ``>>``, ``&``, ``^``, ``|``, ``~``. Provides defaults for :func:`float`,
99 :attr:`Rational.numerator`, and :attr:`Rational.denominator`.
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000100
101
102Notes for type implementors
103---------------------------
104
105Implementors should be careful to make equal numbers equal and hash
106them to the same values. This may be subtle if there are two different
Christian Heimes3feef612008-02-11 06:19:17 +0000107extensions of the real numbers. For example, :class:`fractions.Fraction`
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000108implements :func:`hash` as follows::
109
110 def __hash__(self):
111 if self.denominator == 1:
112 # Get integers right.
113 return hash(self.numerator)
114 # Expensive check, but definitely correct.
115 if self == float(self):
116 return hash(float(self))
117 else:
118 # Use tuple's hash to avoid a high collision rate on
119 # simple fractions.
120 return hash((self.numerator, self.denominator))
121
122
123Adding More Numeric ABCs
124~~~~~~~~~~~~~~~~~~~~~~~~
125
126There are, of course, more possible ABCs for numbers, and this would
127be a poor hierarchy if it precluded the possibility of adding
128those. You can add ``MyFoo`` between :class:`Complex` and
129:class:`Real` with::
130
131 class MyFoo(Complex): ...
132 MyFoo.register(Real)
133
134
135Implementing the arithmetic operations
136~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
137
138We want to implement the arithmetic operations so that mixed-mode
139operations either call an implementation whose author knew about the
140types of both arguments, or convert both to the nearest built in type
141and do the operation there. For subtypes of :class:`Integral`, this
142means that :meth:`__add__` and :meth:`__radd__` should be defined as::
143
144 class MyIntegral(Integral):
145
146 def __add__(self, other):
147 if isinstance(other, MyIntegral):
148 return do_my_adding_stuff(self, other)
149 elif isinstance(other, OtherTypeIKnowAbout):
150 return do_my_other_adding_stuff(self, other)
151 else:
152 return NotImplemented
153
154 def __radd__(self, other):
155 if isinstance(other, MyIntegral):
156 return do_my_adding_stuff(other, self)
157 elif isinstance(other, OtherTypeIKnowAbout):
158 return do_my_other_adding_stuff(other, self)
159 elif isinstance(other, Integral):
160 return int(other) + int(self)
161 elif isinstance(other, Real):
162 return float(other) + float(self)
163 elif isinstance(other, Complex):
164 return complex(other) + complex(self)
165 else:
166 return NotImplemented
167
168
169There are 5 different cases for a mixed-type operation on subclasses
170of :class:`Complex`. I'll refer to all of the above code that doesn't
171refer to ``MyIntegral`` and ``OtherTypeIKnowAbout`` as
172"boilerplate". ``a`` will be an instance of ``A``, which is a subtype
173of :class:`Complex` (``a : A <: Complex``), and ``b : B <:
174Complex``. I'll consider ``a + b``:
175
176 1. If ``A`` defines an :meth:`__add__` which accepts ``b``, all is
177 well.
178 2. If ``A`` falls back to the boilerplate code, and it were to
179 return a value from :meth:`__add__`, we'd miss the possibility
180 that ``B`` defines a more intelligent :meth:`__radd__`, so the
181 boilerplate should return :const:`NotImplemented` from
182 :meth:`__add__`. (Or ``A`` may not implement :meth:`__add__` at
183 all.)
184 3. Then ``B``'s :meth:`__radd__` gets a chance. If it accepts
185 ``a``, all is well.
186 4. If it falls back to the boilerplate, there are no more possible
187 methods to try, so this is where the default implementation
188 should live.
189 5. If ``B <: A``, Python tries ``B.__radd__`` before
190 ``A.__add__``. This is ok, because it was implemented with
191 knowledge of ``A``, so it can handle those instances before
192 delegating to :class:`Complex`.
193
194If ``A<:Complex`` and ``B<:Real`` without sharing any other knowledge,
195then the appropriate shared operation is the one involving the built
196in :class:`complex`, and both :meth:`__radd__` s land there, so ``a+b
197== b+a``.
198
199Because most of the operations on any given type will be very similar,
200it can be useful to define a helper function which generates the
201forward and reverse instances of any given operator. For example,
Christian Heimes3feef612008-02-11 06:19:17 +0000202:class:`fractions.Fraction` uses::
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000203
204 def _operator_fallbacks(monomorphic_operator, fallback_operator):
205 def forward(a, b):
Christian Heimes3feef612008-02-11 06:19:17 +0000206 if isinstance(b, (int, long, Fraction)):
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000207 return monomorphic_operator(a, b)
208 elif isinstance(b, float):
209 return fallback_operator(float(a), b)
210 elif isinstance(b, complex):
211 return fallback_operator(complex(a), b)
212 else:
213 return NotImplemented
214 forward.__name__ = '__' + fallback_operator.__name__ + '__'
215 forward.__doc__ = monomorphic_operator.__doc__
216
217 def reverse(b, a):
Christian Heimes3feef612008-02-11 06:19:17 +0000218 if isinstance(a, Rational):
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000219 # Includes ints.
220 return monomorphic_operator(a, b)
221 elif isinstance(a, numbers.Real):
222 return fallback_operator(float(a), float(b))
223 elif isinstance(a, numbers.Complex):
224 return fallback_operator(complex(a), complex(b))
225 else:
226 return NotImplemented
227 reverse.__name__ = '__r' + fallback_operator.__name__ + '__'
228 reverse.__doc__ = monomorphic_operator.__doc__
229
230 return forward, reverse
231
232 def _add(a, b):
233 """a + b"""
Christian Heimes3feef612008-02-11 06:19:17 +0000234 return Fraction(a.numerator * b.denominator +
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000235 b.numerator * a.denominator,
236 a.denominator * b.denominator)
237
238 __add__, __radd__ = _operator_fallbacks(_add, operator.add)
239
240 # ...