3.3. Functools#
functools is a built-in Python library to work with functions efficiently. This section will show you some useful methods of functools.
3.3.1. functools.partial: Generate a New Function with Fewer Arguments#
If you want to fix some arguments of a function and generate a new function with fewer arguments, use functools.partial
.
In the code below, I use partial
to create a new function with only x
as the argument.
from functools import partial
def linear_func(x, a, b):
return a * x + b
linear_func_partial = partial(linear_func, a=2, b=3)
print(linear_func_partial(2))
print(linear_func_partial(4))
7
11
3.3.2. functools.singledispatch: Call Another Function Based on the Type of the Current Function’s Argument#
Normally, to call another function based on the type of the current function’s argument, we use an if-else statement:
data = {"a": [1, 2, 3], "b": [4, 5, 6]}
data2 = [{"a": [1, 2, 3]}, {"b": [4, 5, 6]}]
def process_data(data):
if isinstance(data, dict):
process_dict(data)
else:
process_list(data)
def process_dict(data: dict):
print("Dict is processed")
def process_list(data: list):
print("List is processed")
process_data(data)
Dict is processed
process_data(data2)
List is processed
With singledispatch
, you don’t need to use an if-else statement to call an appropriate function. singledispatch
will choose the right function based on the type of current function’s first argument.
from functools import singledispatch
@singledispatch
def process_data2(data):
raise NotImplementedError("Please implement process_data2")
@process_data2.register
def process_dict2(data: dict):
print("Dict is processed")
@process_data2.register
def process_list2(data: list):
print("List is processed")
process_data2(data)
Dict is processed
process_data2(data2)
List is processed
3.3.3. functools.reduce: Apply Function Cumulatively to the Items of Iterable#
If you want to apply a function of two arguments cumulatively to the items of iterable from left to right, use functools’s reduce. This method reduces the iterable to a single value.
In the code below, 3
is the result of the function add_nums(2, 1)
. 3
is then used as the first argument of the function add_nums(3, 2)
.
from functools import reduce
def add_nums(num1, num2):
res = num1 + num2
print(f"{num1} + {num2} = {res}")
return res
print(reduce(add_nums, [1, 2, 3], 2))
2 + 1 = 3
3 + 2 = 5
5 + 3 = 8
8
3.3.4. Combine Reduce and Operator Methods#
You can combine functools.reduce
with a method from operator to achieve the similar functionality and make the code more readable.
import functools
import operator
# 2+1=3, 3+2=5, 5+3=8
functools.reduce(operator.add, [1, 2, 3], 2)
8