[2] | 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 |
|
---|
[391] | 10 | The :mod:`numbers` module (:pep:`3141`) defines a hierarchy of numeric
|
---|
| 11 | :term:`abstract base classes <abstract base class>` which progressively define
|
---|
| 12 | more operations. None of the types defined in this module can be instantiated.
|
---|
[2] | 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 |
|
---|
| 21 | The 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 |
|
---|
[391] | 34 | Abstract. Retrieves the real component of this number.
|
---|
[2] | 35 |
|
---|
| 36 | .. attribute:: imag
|
---|
| 37 |
|
---|
[391] | 38 | Abstract. Retrieves the imaginary component of this number.
|
---|
[2] | 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 |
|
---|
[391] | 50 | In short, those are: a conversion to :class:`float`, :func:`math.trunc`,
|
---|
[2] | 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 |
|
---|
[391] | 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: ``<<``, ``>>``, ``&``, ``^``, ``|``, ``~``.
|
---|
[2] | 80 |
|
---|
| 81 |
|
---|
| 82 | Notes for type implementors
|
---|
| 83 | ---------------------------
|
---|
| 84 |
|
---|
| 85 | Implementors should be careful to make equal numbers equal and hash
|
---|
| 86 | them to the same values. This may be subtle if there are two different
|
---|
| 87 | extensions of the real numbers. For example, :class:`fractions.Fraction`
|
---|
| 88 | implements :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 |
|
---|
| 103 | Adding More Numeric ABCs
|
---|
| 104 | ~~~~~~~~~~~~~~~~~~~~~~~~
|
---|
| 105 |
|
---|
| 106 | There are, of course, more possible ABCs for numbers, and this would
|
---|
| 107 | be a poor hierarchy if it precluded the possibility of adding
|
---|
| 108 | those. You can add ``MyFoo`` between :class:`Complex` and
|
---|
| 109 | :class:`Real` with::
|
---|
| 110 |
|
---|
| 111 | class MyFoo(Complex): ...
|
---|
| 112 | MyFoo.register(Real)
|
---|
| 113 |
|
---|
| 114 |
|
---|
| 115 | Implementing the arithmetic operations
|
---|
| 116 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
---|
| 117 |
|
---|
| 118 | We want to implement the arithmetic operations so that mixed-mode
|
---|
| 119 | operations either call an implementation whose author knew about the
|
---|
| 120 | types of both arguments, or convert both to the nearest built in type
|
---|
| 121 | and do the operation there. For subtypes of :class:`Integral`, this
|
---|
| 122 | means 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 |
|
---|
| 149 | There are 5 different cases for a mixed-type operation on subclasses
|
---|
| 150 | of :class:`Complex`. I'll refer to all of the above code that doesn't
|
---|
| 151 | refer to ``MyIntegral`` and ``OtherTypeIKnowAbout`` as
|
---|
| 152 | "boilerplate". ``a`` will be an instance of ``A``, which is a subtype
|
---|
| 153 | of :class:`Complex` (``a : A <: Complex``), and ``b : B <:
|
---|
| 154 | Complex``. 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 |
|
---|
| 174 | If ``A <: Complex`` and ``B <: Real`` without sharing any other knowledge,
|
---|
| 175 | then the appropriate shared operation is the one involving the built
|
---|
| 176 | in :class:`complex`, and both :meth:`__radd__` s land there, so ``a+b
|
---|
| 177 | == b+a``.
|
---|
| 178 |
|
---|
| 179 | Because most of the operations on any given type will be very similar,
|
---|
| 180 | it can be useful to define a helper function which generates the
|
---|
| 181 | forward 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 | # ...
|
---|