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