2 min read

Python Functools Module

The functools module is for higher-order functions: functions that act on or return other functions. In general, any callable object can be treated as a function for the purposes of this module.

Importing the Module

import functools

Caching (lru_cache)

Decorator to wrap a function with a memoizing callable that saves up to the maxsize most recent calls. It can save time when an expensive or I/O bound function is periodically called with the same arguments.

import functools

@functools.lru_cache(maxsize=128)
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(30))
print(fibonacci.cache_info())

Partial Functions (partial)

Return a new partial object which when called will behave like the original function called with the positional arguments args and keyword arguments keywords.

import functools

def power(base, exponent):
    return base ** exponent

# Create a new function that squares a number
square = functools.partial(power, exponent=2)

print(square(5)) # Output: 25

Reduce (reduce)

Apply a function of two arguments cumulatively to the items of a sequence, from left to right, so as to reduce the sequence to a single value.

import functools

# Calculate the product of a list
items = [1, 2, 3, 4, 5]
product = functools.reduce(lambda x, y: x * y, items)

print(product) # Output: 120 (1*2*3*4*5)

Decorator Metadata (wraps)

This is a convenience function for invoking update_wrapper() as a function decorator when defining a wrapper function. It copies the docstring, name, and other metadata from the wrapped function to the wrapper.

import functools

def my_decorator(f):
    @functools.wraps(f)
    def wrapper(*args, **kwargs):
        print('Calling decorated function')
        return f(*args, **kwargs)
    return wrapper

@my_decorator
def example():
    """Docstring"""
    print('Called example function')

print(example.__name__) # Output: example (without @wraps it would be 'wrapper')
print(example.__doc__)  # Output: Docstring

Total Ordering (total_ordering)

Given a class defining one or more rich comparison ordering methods, this class decorator supplies the rest.

import functools

@functools.total_ordering
class Student:
    def __init__(self, grade):
        self.grade = grade

    def __eq__(self, other):
        return self.grade == other.grade

    def __lt__(self, other):
        return self.grade < other.grade

s1 = Student(90)
s2 = Student(80)

print(s1 > s2) # True (automatically generated from __lt__)

programming/python/python