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