0Pricing
Python Academy · Lesson

functools: partial and reduce

Create specialized functions with partial and fold sequences with reduce.

functools: partial and reduce is a free Python Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Python Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

functools Overview

functools is a standard-library module of higher-order functions that operate on or return other functions.

import functools

# partial, reduce, lru_cache, wraps, cached_property ...
print(dir(functools))

partial()

functools.partial(func, *args, **kw) creates a new callable with some arguments pre-filled.

import functools

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

square = functools.partial(power, exp=2)
cube   = functools.partial(power, exp=3)

print(square(4))  # 16
print(cube(3))    # 27

partial with Methods

Use partial to adapt methods with fixed parameters for use as callbacks or event handlers.

import functools, logging

logger = logging.getLogger("app")
log_error = functools.partial(logger.log, logging.ERROR)

log_error("Something went wrong")

partial vs lambda

partial is preferred over lambda for pre-filling arguments because it is picklable, has a good repr, and preserves the docstring.

import functools

mul = lambda x, y: x * y

double_lambda = lambda x: mul(x, 2)            # lambda approach
double_partial = functools.partial(mul, y=2)   # partial approach

print(double_partial(5))   # 10

reduce()

functools.reduce(func, iterable, initial) folds the iterable left-to-right using a binary function.

import functools, operator

total = functools.reduce(operator.add, [1,2,3,4,5])
print(total)   # 15

product = functools.reduce(operator.mul, [1,2,3,4,5], 1)
print(product) # 120

Building max() with reduce

Illustrate reduce by reimplementing max():

import functools

def my_max(seq):
    return functools.reduce(lambda a, b: a if a > b else b, seq)

print(my_max([3, 1, 4, 1, 5, 9]))  # 9

Flattening Nested Lists

Use reduce with operator.iconcat to flatten one level of nesting.

import functools, operator

nested = [[1,2],[3,4],[5]]
flat = functools.reduce(operator.iconcat, nested, [])
print(flat)  # [1, 2, 3, 4, 5]

partial for URL Building

A practical partial pattern: fix a base URL and create specialised request helpers.

import functools, urllib.request

def fetch(base, path):
    url = base.rstrip("/") + "/" + path.lstrip("/")
    with urllib.request.urlopen(url) as r:
        return r.read()

github = functools.partial(fetch, "https://api.github.com")
# github("/users/octocat")

wraps(): Preserving Metadata

When writing decorators, use @functools.wraps(wrapped) so the wrapper preserves the original function's name and docstring.

import functools

def decorator(func):
    @functools.wraps(func)
    def wrapper(*args, **kw):
        return func(*args, **kw)
    return wrapper

@decorator
def greet(name):
    """Say hello."""
    return f"Hello, {name}"

print(greet.__name__)  # greet
print(greet.__doc__)   # Say hello.

total_ordering

@functools.total_ordering fills in missing comparison methods when you define __eq__ and one of __lt__/__le__/__gt__/__ge__.

import functools

@functools.total_ordering
class Version:
    def __init__(self, major, minor):
        self.v = (major, minor)
    def __eq__(self, o): return self.v == o.v
    def __lt__(self, o): return self.v < o.v

print(Version(1,2) >= Version(1,1))  # True

singledispatch

@functools.singledispatch creates a function that dispatches to different implementations based on the type of the first argument.

import functools

@functools.singledispatch
def process(arg):
    raise NotImplementedError(type(arg))

@process.register(int)
def _(n): return n * 2

@process.register(str)
def _(s): return s.upper()

print(process(5))     # 10
print(process("hi"))  # HI

Quick Check

What does functools.partial(pow, 2) create?

Recap

partial pre-fills function arguments; reduce folds a sequence with a binary function; wraps preserves decorator metadata; total_ordering fills comparison methods; singledispatch dispatches by type.

Frequently asked questions

Is the “functools: partial and reduce” lesson free?

Yes — the full text of “functools: partial and reduce” is free to read here on the web, and the Python Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Python Academy course, upgrade to CoddyKit PRO.

What will I learn in “functools: partial and reduce”?

Create specialized functions with partial and fold sequences with reduce. You practise Python Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Python Academy?

No prior experience is required. Python Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “functools: partial and reduce” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Python Academy lesson?

Yes. Every Python Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. itertools: Infinite and Finite Iterators
  2. itertools: Combinatorics
  3. functools: partial and reduce
  4. functools: lru_cache and cached_property
← Back to Python Academy