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