mirror of
https://github.com/python/cpython.git
synced 2025-11-01 18:51:43 +00:00
Add reference implementation for PEP 443
PEP accepted: http://mail.python.org/pipermail/python-dev/2013-June/126734.html
This commit is contained in:
parent
072318b178
commit
6f69251980
6 changed files with 614 additions and 55 deletions
|
|
@ -6,6 +6,7 @@
|
|||
.. moduleauthor:: Peter Harris <scav@blueyonder.co.uk>
|
||||
.. moduleauthor:: Raymond Hettinger <python@rcn.com>
|
||||
.. moduleauthor:: Nick Coghlan <ncoghlan@gmail.com>
|
||||
.. moduleauthor:: Łukasz Langa <lukasz@langa.pl>
|
||||
.. sectionauthor:: Peter Harris <scav@blueyonder.co.uk>
|
||||
|
||||
**Source code:** :source:`Lib/functools.py`
|
||||
|
|
@ -186,6 +187,115 @@ The :mod:`functools` module defines the following functions:
|
|||
*sequence* contains only one item, the first item is returned.
|
||||
|
||||
|
||||
.. decorator:: singledispatch(default)
|
||||
|
||||
Transforms a function into a single-dispatch generic function. A **generic
|
||||
function** is composed of multiple functions implementing the same operation
|
||||
for different types. Which implementation should be used during a call is
|
||||
determined by the dispatch algorithm. When the implementation is chosen
|
||||
based on the type of a single argument, this is known as **single
|
||||
dispatch**.
|
||||
|
||||
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::
|
||||
|
||||
>>> from functools import singledispatch
|
||||
>>> @singledispatch
|
||||
... def fun(arg, verbose=False):
|
||||
... if verbose:
|
||||
... print("Let me just say,", end=" ")
|
||||
... print(arg)
|
||||
|
||||
To add overloaded implementations to the function, use the :func:`register`
|
||||
attribute of the generic function. It is a decorator, taking a type
|
||||
parameter and decorating a function implementing the operation for that
|
||||
type::
|
||||
|
||||
>>> @fun.register(int)
|
||||
... def _(arg, verbose=False):
|
||||
... if verbose:
|
||||
... print("Strength in numbers, eh?", end=" ")
|
||||
... print(arg)
|
||||
...
|
||||
>>> @fun.register(list)
|
||||
... def _(arg, verbose=False):
|
||||
... if verbose:
|
||||
... print("Enumerate this:")
|
||||
... for i, elem in enumerate(arg):
|
||||
... print(i, elem)
|
||||
|
||||
To enable registering lambdas and pre-existing functions, the
|
||||
:func:`register` attribute can 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::
|
||||
|
||||
>>> @fun.register(float)
|
||||
... @fun.register(Decimal)
|
||||
... def fun_num(arg, verbose=False):
|
||||
... if verbose:
|
||||
... print("Half of your number:", end=" ")
|
||||
... print(arg / 2)
|
||||
...
|
||||
>>> fun_num is fun
|
||||
False
|
||||
|
||||
When called, the generic function dispatches on the type of the first
|
||||
argument::
|
||||
|
||||
>>> fun("Hello, world.")
|
||||
Hello, world.
|
||||
>>> fun("test.", verbose=True)
|
||||
Let me just say, test.
|
||||
>>> fun(42, verbose=True)
|
||||
Strength in numbers, eh? 42
|
||||
>>> fun(['spam', 'spam', 'eggs', 'spam'], verbose=True)
|
||||
Enumerate this:
|
||||
0 spam
|
||||
1 spam
|
||||
2 eggs
|
||||
3 spam
|
||||
>>> fun(None)
|
||||
Nothing.
|
||||
>>> fun(1.23)
|
||||
0.615
|
||||
|
||||
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
|
||||
implementation is found.
|
||||
|
||||
To check which implementation will the generic function choose for
|
||||
a given type, use the ``dispatch()`` attribute::
|
||||
|
||||
>>> fun.dispatch(float)
|
||||
<function fun_num at 0x1035a2840>
|
||||
>>> fun.dispatch(dict) # note: default implementation
|
||||
<function fun at 0x103fe0000>
|
||||
|
||||
To access all registered implementations, use the read-only ``registry``
|
||||
attribute::
|
||||
|
||||
>>> fun.registry.keys()
|
||||
dict_keys([<class 'NoneType'>, <class 'int'>, <class 'object'>,
|
||||
<class 'decimal.Decimal'>, <class 'list'>,
|
||||
<class 'float'>])
|
||||
>>> fun.registry[float]
|
||||
<function fun_num at 0x1035a2840>
|
||||
>>> fun.registry[object]
|
||||
<function fun at 0x103fe0000>
|
||||
|
||||
.. versionadded:: 3.4
|
||||
|
||||
|
||||
.. function:: update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)
|
||||
|
||||
Update a *wrapper* function to look like the *wrapped* function. The optional
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue