What is `functools.partial`, and how does it differ from a lambda?
Quick Answer
`functools.partial(func, *args, **kwargs)` creates a new callable with some arguments **pre-filled**, returning a real, introspectable object (with `.func`, `.args`, `.keywords` attributes) rather than a throwaway closure. It's functionally similar to a lambda that forwards extra arguments, but is more explicit, slightly faster, picklable (lambdas aren't), and self-documenting about which arguments are fixed.
Detailed Answer
Basic usage
from functools import partial
def power(base, exponent):
return base ** exponent
square = partial(power, exponent=2)
cube = partial(power, exponent=3)
square(5) # 25
cube(5) # 125
square and cube are new callables with exponent pre-bound;
calling them only needs the remaining argument (base).
Equivalent lambda
square = lambda base: power(base, exponent=2)
Functionally similar for simple cases, but partial has real advantages:
- Introspectable:
square.func,square.args,square.keywordslet you inspect what's pre-filled — useful for debugging or building generic tooling around partially-applied callables. - Picklable:
partialobjects can be pickled (as long as the underlying function and bound arguments are), which matters formultiprocessing(worker functions passed to a process pool must be picklable) — alambdacannot be pickled at all. - Clearer intent:
partial(power, exponent=2)reads as "power, with exponent fixed at 2," which is more self-documenting than a lambda wrapping a call.
A common real use: multiprocessing/callback APIs
from functools import partial
from multiprocessing import Pool
def process(item, config):
return item * config["factor"]
with Pool() as pool:
results = pool.map(partial(process, config={"factor": 3}), [1, 2, 3])
Since worker functions passed across process boundaries must be picklable,
partial is the standard way to "bake in" extra arguments for a function
used as a callback, where a lambda would fail to pickle.
Interview-ready summary: partial pre-fills some of a function's
arguments and returns a new, real callable object — functionally similar
to a wrapping lambda, but introspectable and picklable, which matters for
tooling and multiprocessing in particular.