diff options
Diffstat (limited to 'Doc/library/functools.rst')
-rw-r--r-- | Doc/library/functools.rst | 177 |
1 files changed, 174 insertions, 3 deletions
diff --git a/Doc/library/functools.rst b/Doc/library/functools.rst index 3c946e3..77cd838 100644 --- a/Doc/library/functools.rst +++ b/Doc/library/functools.rst @@ -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` @@ -133,15 +134,34 @@ The :mod:`functools` module defines the following functions: @total_ordering class Student: + def _is_valid_operand(self, other): + return (hasattr(other, "lastname") and + hasattr(other, "firstname")) def __eq__(self, other): + if not self._is_valid_operand(other): + return NotImplemented return ((self.lastname.lower(), self.firstname.lower()) == (other.lastname.lower(), other.firstname.lower())) def __lt__(self, other): + if not self._is_valid_operand(other): + return NotImplemented return ((self.lastname.lower(), self.firstname.lower()) < (other.lastname.lower(), other.firstname.lower())) + .. note:: + + While this decorator makes it easy to create well behaved totally + ordered types, it *does* come at the cost of slower execution and + more complex stack traces for the derived comparison methods. If + performance benchmarking indicates this is a bottleneck for a given + application, implementing all six rich comparison methods instead is + likely to provide an easy speed boost. + .. versionadded:: 3.2 + .. versionchanged:: 3.4 + Returning NotImplemented from the underlying comparison function for + unrecognised types is now supported. .. function:: partial(func, *args, **keywords) @@ -174,6 +194,48 @@ The :mod:`functools` module defines the following functions: 18 +.. class:: partialmethod(func, *args, **keywords) + + Return a new :class:`partialmethod` descriptor which behaves + like :class:`partial` except that it is designed to be used as a method + definition rather than being directly callable. + + *func* must be a :term:`descriptor` or a callable (objects which are both, + like normal functions, are handled as descriptors). + + When *func* is a descriptor (such as a normal Python function, + :func:`classmethod`, :func:`staticmethod`, :func:`abstractmethod` or + another instance of :class:`partialmethod`), calls to ``__get__`` are + delegated to the underlying descriptor, and an appropriate + :class:`partial` object returned as the result. + + When *func* is a non-descriptor callable, an appropriate bound method is + created dynamically. This behaves like a normal Python function when + used as a method: the *self* argument will be inserted as the first + positional argument, even before the *args* and *keywords* supplied to + the :class:`partialmethod` constructor. + + Example:: + + >>> class Cell(object): + ... @property + ... def alive(self): + ... return self._alive + ... def set_state(self, state): + ... self._alive = bool(state) + ... set_alive = partialmethod(set_state, True) + ... set_dead = partialmethod(set_state, False) + ... + >>> c = Cell() + >>> c.alive + False + >>> c.set_alive() + >>> c.alive + True + + .. versionadded:: 3.4 + + .. function:: reduce(function, iterable[, initializer]) Apply *function* of two arguments cumulatively to the items of *sequence*, from @@ -198,6 +260,111 @@ The :mod:`functools` module defines the following functions: return value +.. decorator:: singledispatch(default) + + Transforms a function into a :term:`single-dispatch <single + 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:: + + >>> 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 @@ -212,8 +379,8 @@ The :mod:`functools` module defines the following functions: To allow access to the original function for introspection and other purposes (e.g. bypassing a caching decorator such as :func:`lru_cache`), this function - automatically adds a __wrapped__ attribute to the wrapper that refers to - the original function. + automatically adds a ``__wrapped__`` attribute to the wrapper that refers to + the function being wrapped. The main intended use for this function is in :term:`decorator` functions which wrap the decorated function and return the wrapper. If the wrapper function is @@ -236,6 +403,11 @@ The :mod:`functools` module defines the following functions: .. versionchanged:: 3.2 Missing attributes no longer trigger an :exc:`AttributeError`. + .. versionchanged:: 3.4 + The ``__wrapped__`` attribute now always refers to the wrapped + function, even if that function defined a ``__wrapped__`` attribute. + (see :issue:`17482`) + .. decorator:: wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES) @@ -301,4 +473,3 @@ differences. For instance, the :attr:`__name__` and :attr:`__doc__` attributes are not created automatically. Also, :class:`partial` objects defined in classes behave like static methods and do not transform into bound methods during instance attribute look-up. - |