Skip to content

Commit

Permalink
bpo-45762: Improve docs for @singledispatch/``@singledispatchmeth…
Browse files Browse the repository at this point in the history
…od`` (pythonGH-29426) (pythonGH-29431)

(cherry picked from commit 71e8a3e)

Co-authored-by: Alex Waygood <[email protected]>
  • Loading branch information
miss-islington and AlexWaygood authored Nov 5, 2021
1 parent bcb236c commit 279a7a0
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 22 deletions.
48 changes: 26 additions & 22 deletions Doc/library/functools.rst
Original file line number Diff line number Diff line change
Expand Up @@ -402,8 +402,8 @@ The :mod:`functools` module defines the following functions:
dispatch>` :term:`generic function`.

To define a generic function, decorate it with the ``@singledispatch``
decorator. Note that the dispatch happens on the type of the first argument,
create your function accordingly::
decorator. When defining a function using ``@singledispatch``, note that the
dispatch happens on the type of the first argument::

>>> from functools import singledispatch
>>> @singledispatch
Expand All @@ -413,9 +413,9 @@ The :mod:`functools` module defines the following functions:
... print(arg)

To add overloaded implementations to the function, use the :func:`register`
attribute of the generic function. It is a decorator. For functions
annotated with types, the decorator will infer the type of the first
argument automatically::
attribute of the generic function, which can be used as a decorator. For
functions annotated with types, the decorator will infer the type of the
first argument automatically::

>>> @fun.register
... def _(arg: int, verbose=False):
Expand All @@ -441,17 +441,17 @@ The :mod:`functools` module defines the following functions:
...


To enable registering lambdas and pre-existing functions, the
:func:`register` attribute can be used in a functional form::
To enable registering :term:`lambdas<lambda>` and pre-existing functions,
the :func:`register` attribute can also be used in a functional form::

>>> def nothing(arg, verbose=False):
... print("Nothing.")
...
>>> fun.register(type(None), nothing)

The :func:`register` attribute returns the undecorated function which
enables decorator stacking, pickling, as well as creating unit tests for
each variant independently::
The :func:`register` attribute returns the undecorated function. This
enables decorator stacking, :mod:`pickling<pickle>`, and the creation
of unit tests for each variant independently::

>>> @fun.register(float)
... @fun.register(Decimal)
Expand Down Expand Up @@ -486,11 +486,12 @@ The :mod:`functools` module defines the following functions:
Where there is no registered implementation for a specific type, its
method resolution order is used to find a more generic implementation.
The original function decorated with ``@singledispatch`` is registered
for the base ``object`` type, which means it is used if no better
for the base :class:`object` type, which means it is used if no better
implementation is found.

If an implementation registered to :term:`abstract base class`, virtual
subclasses will be dispatched to that implementation::
If an implementation is registered to an :term:`abstract base class`,
virtual subclasses of the base class will be dispatched to that
implementation::

>>> from collections.abc import Mapping
>>> @fun.register
Expand All @@ -503,7 +504,7 @@ The :mod:`functools` module defines the following functions:
>>> fun({"a": "b"})
a => b

To check which implementation will the generic function choose for
To check which implementation the generic function will choose for
a given type, use the ``dispatch()`` attribute::

>>> fun.dispatch(float)
Expand All @@ -526,7 +527,7 @@ The :mod:`functools` module defines the following functions:
.. versionadded:: 3.4

.. versionchanged:: 3.7
The :func:`register` attribute supports using type annotations.
The :func:`register` attribute now supports using type annotations.


.. class:: singledispatchmethod(func)
Expand All @@ -535,8 +536,9 @@ The :mod:`functools` module defines the following functions:
dispatch>` :term:`generic function`.

To define a generic method, decorate it with the ``@singledispatchmethod``
decorator. Note that the dispatch happens on the type of the first non-self
or non-cls argument, create your function accordingly::
decorator. When defining a function using ``@singledispatchmethod``, note
that the dispatch happens on the type of the first non-*self* or non-*cls*
argument::

class Negator:
@singledispatchmethod
Expand All @@ -552,9 +554,10 @@ The :mod:`functools` module defines the following functions:
return not arg

``@singledispatchmethod`` supports nesting with other decorators such as
``@classmethod``. Note that to allow for ``dispatcher.register``,
``singledispatchmethod`` must be the *outer most* decorator. Here is the
``Negator`` class with the ``neg`` methods being class bound::
:func:`@classmethod<classmethod>`. Note that to allow for
``dispatcher.register``, ``singledispatchmethod`` must be the *outer most*
decorator. Here is the ``Negator`` class with the ``neg`` methods bound to
the class, rather than an instance of the class::

class Negator:
@singledispatchmethod
Expand All @@ -572,8 +575,9 @@ The :mod:`functools` module defines the following functions:
def _(cls, arg: bool):
return not arg

The same pattern can be used for other similar decorators: ``staticmethod``,
``abstractmethod``, and others.
The same pattern can be used for other similar decorators:
:func:`@staticmethod<staticmethod>`,
:func:`@abstractmethod<abc.abstractmethod>`, and others.

.. versionadded:: 3.8

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Improve documentation for :func:`functools.singledispatch` and
:class:`functools.singledispatchmethod`.

0 comments on commit 279a7a0

Please sign in to comment.