The functools
module in the standard library provides functions and classes for manipulating functions. The primary tool defined in the module is the partial
class, which as we will see in a while, allows the partial application of a function. This means that a callable object is created with some of the arguments already filled in, reducing the number of arguments that must be supplied to subsequent calls.
The module also provides a number of decorators which can be used to wrap functions and classes in order to extend them with additional capabilities.
Partial Objects
The partial
class makes it possible to create a version of a callable object( e.g functions) with some of the arguments pre-filled.
partial(callable, *args, **kwargs)
In the above example, we created a new partial function, myprint(),
from the builtin print()
function. The original print()
function would have separated each item with a space, but by using functools.partial
function, we were able to set the sep
keyword argument to a comma and a space( ', ').
In the following example we use a user-defined function to create a partial function.
The following example uses a class rather than a function as the callable
Acquire properties of the original callable
By default, the returned partial object, does not inherit the __name__
and the __doc__
attributes from the original callable object.This attributes are very essential especially for debugging purposes.
As you can see above, myprint()
function does not inherit the docstring of the print()
function, from which it is a partial object.
The update_wrapper()
function attaches the relevant information to the partial object from another object.
partialmethod class
The partial
class, as we have seen, works with bare functions. The partialmethod
class similarly creates partial objects but from methods. The partial method should be defined inside the class as shown below.
Functions defined in the functools module
Apart from the two classes that we have looked at i.e partial
and partialmethod
, the module also defines several utility functions that can be used to further manipulate functions through decoration.
cmp_to_key()
Some high order functions such builtin sorted()
, filter()
, max()
, and min()
, takes an optional parameter called key which
is used to specify a particular function to be applied to each element of the iterable prior to making comparisons.
The cmp_to_key()
function is used to create a key function from a traditional comparison function. The function given as an argument must return either 1, 0, or -1 depending on the arguments it receives.
reduce()
The reduce()
function applies a given function cumulatively to an iterable. It typically takes two arguments: a function and an iterable, it then applies the function cumulatively on the elements of the given iterable.
reduce(func, iterable)
The function given as func
must accept two arguments.
cache()
The cache()
function is used to cache the result of an expensive computation for future use. This means that if the same function is called with the same parameters, the results are cached and the computation does not need to be redone.
lru_cache()
The lru_cache()
function implements a least recently used (LRU) cache for efficient memoization of a function. When the function is called, the lru_cache()
will store any inputs and outputs of the function in an order of least recently used. When the cache is full, the least recently used items are discarded to make space for new data. This is beneficial as it allows the cache to store more relevant data rather than having to store all data from the function call.
singledispatch()
The singledispatch()
decorator function is used to create functions that can dispatch on the type of a single argument such that certain behaviors are dependent on the type. When decorated with singledispatch()
, a function becomes a "generic function", meaning that it can have multiple different implementations, depending on the type of the argument passed to it.
The implementation for a particular type is registered using the register()
method of the decorated function.
@total_ordering
The @functools.total_ordering()
is used to automatically fill in comparison methods for a class by defining only two of the six rich comparison methods (__lt__
, __le__
, __eq__
, __ne__
, __gt__
and __ge__
) . This is typically achieved by decorating the class with the @total_ordering
decorator and defining the __eq__
method alongside any other of (__lt__
, __le__
,__gt__
, __ge__
).