Table of contents
The Python programming language is known for its flexibility and powerful standard library. One module that exemplifies this is functools
. The functools
module provides higher-order functions and operations on callable objects. In this blog post, we'll see some of the key features of the functools
module with illustrative code examples.
Partial Functions
Partial functions allow us to fix a certain number of arguments of a function and generate a new function. This can be incredibly useful in situations where you have a function that requires several arguments, but you frequently call it with some fixed parameters.
- Using a Normal Function:
def squared(num):
return pow(num, 2)
print(list(map(squared, range(0, 10))))
#[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
A function named squared
is defined that takes a number num
and returns its square using the built-in pow()
function. We used the map()
function to apply the squared
function to each element in the range from 0 to 9. The result is converted into a list and printed.
- Using
partial()
from thefunctools
module:
from functools import partial
print(list(map(partial(pow, exp=2), range(0, 10))))
#[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Here we import the partial
function from the functools
module. The partial()
is used to fix the exponent argument (exp
) of the pow()
function to 2. The map()
function is used to apply this partially applied pow()
function to each element in the range from 0 to 9.
Wrapping Functions
The functools
provides tools for creating wrapper functions. These wrapper functions can add behavior before and/or after the wrapped function is called. When used as a decorator for a wrapper function, it copies the metadata (like function name and docstring) from the original function to the wrapper function. This prevents confusion and bugs that can occur when the wrapper function's metadata doesn't match the original function's metadata
from functools import wraps
def deco(func):
@wraps(func)
def wrap(*args, **kwargs):
print("before")
result = func(*args, **kwargs)
print("after")
return result
return wrap
@deco
def orig():
print("original executing")
print("original name:", orig.__name__)
print("rriginal docstring:", orig.__doc__)
Reducing
The functools.reduce()
function is like a conveyor belt where items come one after the other. It continuously applies a function to pairs of items as they come, rolling from the left to the right of a list. Each time it combines two items, it moves on to the next pair until it finishes the list. So, it's like a machine that keeps crunching pairs of items until it gets a single result.
from functools import reduce
numbers = [1, 2, 3, 4]
product = reduce(lambda x, y: x * y, numbers)
print(product)
#120 (1 * 2 * 3 * 4)
In give code the reduce()
function takes two arguments: a function (lambda x, y: x * y
) and an iterable (numbers
). The lambda function lambda x, y: x * y
takes two arguments (x
and y
) and returns their product. reduce()
applies this function gradually to the items of the iterable from left to right. In other words, it calculates the product of the first two numbers, then multiplies that result with the third number, and so on, until it reaches the end of the list.