mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 03:44:55 +00:00 
			
		
		
		
	- Rename reST target name for collections ABCs to avoid collisions - Add link to importlib ABCs (collections, numbers and io ABCs were already linked) - Link to glossary entry from numbers module doc (other modules already do it)
		
			
				
	
	
		
			218 lines
		
	
	
	
		
			7.8 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			218 lines
		
	
	
	
		
			7.8 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
:mod:`numbers` --- Numeric abstract base classes
 | 
						|
================================================
 | 
						|
 | 
						|
.. module:: numbers
 | 
						|
   :synopsis: Numeric abstract base classes (Complex, Real, Integral, etc.).
 | 
						|
 | 
						|
 | 
						|
The :mod:`numbers` module (:pep:`3141`) defines a hierarchy of numeric
 | 
						|
:term:`abstract base classes <abstract base class>` which progressively define
 | 
						|
more operations.  None of the types defined in this module can be instantiated.
 | 
						|
 | 
						|
 | 
						|
.. class:: Number
 | 
						|
 | 
						|
   The root of the numeric hierarchy. If you just want to check if an argument
 | 
						|
   *x* is a number, without caring what kind, use ``isinstance(x, Number)``.
 | 
						|
 | 
						|
 | 
						|
The numeric tower
 | 
						|
-----------------
 | 
						|
 | 
						|
.. class:: Complex
 | 
						|
 | 
						|
   Subclasses of this type describe complex numbers and include the operations
 | 
						|
   that work on the built-in :class:`complex` type. These are: conversions to
 | 
						|
   :class:`complex` and :class:`bool`, :attr:`.real`, :attr:`.imag`, ``+``,
 | 
						|
   ``-``, ``*``, ``/``, :func:`abs`, :meth:`conjugate`, ``==``, and ``!=``. All
 | 
						|
   except ``-`` and ``!=`` are abstract.
 | 
						|
 | 
						|
   .. attribute:: real
 | 
						|
 | 
						|
      Abstract. Retrieves the real component of this number.
 | 
						|
 | 
						|
   .. attribute:: imag
 | 
						|
 | 
						|
      Abstract. Retrieves the imaginary component of this number.
 | 
						|
 | 
						|
   .. method:: conjugate()
 | 
						|
 | 
						|
      Abstract. Returns the complex conjugate. For example, ``(1+3j).conjugate()
 | 
						|
      == (1-3j)``.
 | 
						|
 | 
						|
.. class:: Real
 | 
						|
 | 
						|
   To :class:`Complex`, :class:`Real` adds the operations that work on real
 | 
						|
   numbers.
 | 
						|
 | 
						|
   In short, those are: a conversion to :class:`float`, :func:`math.trunc`,
 | 
						|
   :func:`round`, :func:`math.floor`, :func:`math.ceil`, :func:`divmod`, ``//``,
 | 
						|
   ``%``, ``<``, ``<=``, ``>``, and ``>=``.
 | 
						|
 | 
						|
   Real also provides defaults for :func:`complex`, :attr:`~Complex.real`,
 | 
						|
   :attr:`~Complex.imag`, and :meth:`~Complex.conjugate`.
 | 
						|
 | 
						|
 | 
						|
.. class:: Rational
 | 
						|
 | 
						|
   Subtypes :class:`Real` and adds
 | 
						|
   :attr:`~Rational.numerator` and :attr:`~Rational.denominator` properties, which
 | 
						|
   should be in lowest terms. With these, it provides a default for
 | 
						|
   :func:`float`.
 | 
						|
 | 
						|
   .. attribute:: numerator
 | 
						|
 | 
						|
      Abstract.
 | 
						|
 | 
						|
   .. attribute:: denominator
 | 
						|
 | 
						|
      Abstract.
 | 
						|
 | 
						|
 | 
						|
.. class:: Integral
 | 
						|
 | 
						|
   Subtypes :class:`Rational` and adds a conversion to :class:`int`.
 | 
						|
   Provides defaults for :func:`float`, :attr:`~Rational.numerator`, and
 | 
						|
   :attr:`~Rational.denominator`, and bit-string operations: ``<<``,
 | 
						|
   ``>>``, ``&``, ``^``, ``|``, ``~``.
 | 
						|
 | 
						|
 | 
						|
Notes for type implementors
 | 
						|
---------------------------
 | 
						|
 | 
						|
Implementors should be careful to make equal numbers equal and hash
 | 
						|
them to the same values. This may be subtle if there are two different
 | 
						|
extensions of the real numbers. For example, :class:`fractions.Fraction`
 | 
						|
implements :func:`hash` as follows::
 | 
						|
 | 
						|
    def __hash__(self):
 | 
						|
        if self.denominator == 1:
 | 
						|
            # Get integers right.
 | 
						|
            return hash(self.numerator)
 | 
						|
        # Expensive check, but definitely correct.
 | 
						|
        if self == float(self):
 | 
						|
            return hash(float(self))
 | 
						|
        else:
 | 
						|
            # Use tuple's hash to avoid a high collision rate on
 | 
						|
            # simple fractions.
 | 
						|
            return hash((self.numerator, self.denominator))
 | 
						|
 | 
						|
 | 
						|
Adding More Numeric ABCs
 | 
						|
~~~~~~~~~~~~~~~~~~~~~~~~
 | 
						|
 | 
						|
There are, of course, more possible ABCs for numbers, and this would
 | 
						|
be a poor hierarchy if it precluded the possibility of adding
 | 
						|
those. You can add ``MyFoo`` between :class:`Complex` and
 | 
						|
:class:`Real` with::
 | 
						|
 | 
						|
    class MyFoo(Complex): ...
 | 
						|
    MyFoo.register(Real)
 | 
						|
 | 
						|
 | 
						|
Implementing the arithmetic operations
 | 
						|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
						|
 | 
						|
We want to implement the arithmetic operations so that mixed-mode
 | 
						|
operations either call an implementation whose author knew about the
 | 
						|
types of both arguments, or convert both to the nearest built in type
 | 
						|
and do the operation there. For subtypes of :class:`Integral`, this
 | 
						|
means that :meth:`__add__` and :meth:`__radd__` should be defined as::
 | 
						|
 | 
						|
    class MyIntegral(Integral):
 | 
						|
 | 
						|
        def __add__(self, other):
 | 
						|
            if isinstance(other, MyIntegral):
 | 
						|
                return do_my_adding_stuff(self, other)
 | 
						|
            elif isinstance(other, OtherTypeIKnowAbout):
 | 
						|
                return do_my_other_adding_stuff(self, other)
 | 
						|
            else:
 | 
						|
                return NotImplemented
 | 
						|
 | 
						|
        def __radd__(self, other):
 | 
						|
            if isinstance(other, MyIntegral):
 | 
						|
                return do_my_adding_stuff(other, self)
 | 
						|
            elif isinstance(other, OtherTypeIKnowAbout):
 | 
						|
                return do_my_other_adding_stuff(other, self)
 | 
						|
            elif isinstance(other, Integral):
 | 
						|
                return int(other) + int(self)
 | 
						|
            elif isinstance(other, Real):
 | 
						|
                return float(other) + float(self)
 | 
						|
            elif isinstance(other, Complex):
 | 
						|
                return complex(other) + complex(self)
 | 
						|
            else:
 | 
						|
                return NotImplemented
 | 
						|
 | 
						|
 | 
						|
There are 5 different cases for a mixed-type operation on subclasses
 | 
						|
of :class:`Complex`. I'll refer to all of the above code that doesn't
 | 
						|
refer to ``MyIntegral`` and ``OtherTypeIKnowAbout`` as
 | 
						|
"boilerplate". ``a`` will be an instance of ``A``, which is a subtype
 | 
						|
of :class:`Complex` (``a : A <: Complex``), and ``b : B <:
 | 
						|
Complex``. I'll consider ``a + b``:
 | 
						|
 | 
						|
    1. If ``A`` defines an :meth:`__add__` which accepts ``b``, all is
 | 
						|
       well.
 | 
						|
    2. If ``A`` falls back to the boilerplate code, and it were to
 | 
						|
       return a value from :meth:`__add__`, we'd miss the possibility
 | 
						|
       that ``B`` defines a more intelligent :meth:`__radd__`, so the
 | 
						|
       boilerplate should return :const:`NotImplemented` from
 | 
						|
       :meth:`__add__`. (Or ``A`` may not implement :meth:`__add__` at
 | 
						|
       all.)
 | 
						|
    3. Then ``B``'s :meth:`__radd__` gets a chance. If it accepts
 | 
						|
       ``a``, all is well.
 | 
						|
    4. If it falls back to the boilerplate, there are no more possible
 | 
						|
       methods to try, so this is where the default implementation
 | 
						|
       should live.
 | 
						|
    5. If ``B <: A``, Python tries ``B.__radd__`` before
 | 
						|
       ``A.__add__``. This is ok, because it was implemented with
 | 
						|
       knowledge of ``A``, so it can handle those instances before
 | 
						|
       delegating to :class:`Complex`.
 | 
						|
 | 
						|
If ``A <: Complex`` and ``B <: Real`` without sharing any other knowledge,
 | 
						|
then the appropriate shared operation is the one involving the built
 | 
						|
in :class:`complex`, and both :meth:`__radd__` s land there, so ``a+b
 | 
						|
== b+a``.
 | 
						|
 | 
						|
Because most of the operations on any given type will be very similar,
 | 
						|
it can be useful to define a helper function which generates the
 | 
						|
forward and reverse instances of any given operator. For example,
 | 
						|
:class:`fractions.Fraction` uses::
 | 
						|
 | 
						|
    def _operator_fallbacks(monomorphic_operator, fallback_operator):
 | 
						|
        def forward(a, b):
 | 
						|
            if isinstance(b, (int, Fraction)):
 | 
						|
                return monomorphic_operator(a, b)
 | 
						|
            elif isinstance(b, float):
 | 
						|
                return fallback_operator(float(a), b)
 | 
						|
            elif isinstance(b, complex):
 | 
						|
                return fallback_operator(complex(a), b)
 | 
						|
            else:
 | 
						|
                return NotImplemented
 | 
						|
        forward.__name__ = '__' + fallback_operator.__name__ + '__'
 | 
						|
        forward.__doc__ = monomorphic_operator.__doc__
 | 
						|
 | 
						|
        def reverse(b, a):
 | 
						|
            if isinstance(a, Rational):
 | 
						|
                # Includes ints.
 | 
						|
                return monomorphic_operator(a, b)
 | 
						|
            elif isinstance(a, numbers.Real):
 | 
						|
                return fallback_operator(float(a), float(b))
 | 
						|
            elif isinstance(a, numbers.Complex):
 | 
						|
                return fallback_operator(complex(a), complex(b))
 | 
						|
            else:
 | 
						|
                return NotImplemented
 | 
						|
        reverse.__name__ = '__r' + fallback_operator.__name__ + '__'
 | 
						|
        reverse.__doc__ = monomorphic_operator.__doc__
 | 
						|
 | 
						|
        return forward, reverse
 | 
						|
 | 
						|
    def _add(a, b):
 | 
						|
        """a + b"""
 | 
						|
        return Fraction(a.numerator * b.denominator +
 | 
						|
                        b.numerator * a.denominator,
 | 
						|
                        a.denominator * b.denominator)
 | 
						|
 | 
						|
    __add__, __radd__ = _operator_fallbacks(_add, operator.add)
 | 
						|
 | 
						|
    # ...
 |