Q&A library Python

How do I fix some arguments of a function in Python?

Python Intermediate functionsfunctoolspartial

Short answer

Use functools.partial to build a new function with some arguments already supplied. It is clearer than a lambda for this purpose and keeps the original function reusable.

The short version

functools.partial creates a new function from an existing one with some arguments already filled in. It is the clean way to specialise a general function, and it reads better than a lambda when all you are doing is pinning arguments.

Fixing an argument

from functools import partial

def apply_tax(amount, rate):
    return amount * (1 + rate)

with_vat = partial(apply_tax, rate=0.2)

with_vat(100)    # 120.0

with_vat is a new function that takes only the amount, because the rate is already supplied. The original apply_tax is untouched and still available with any rate.

Why not a lambda

with_vat = lambda amount: apply_tax(amount, rate=0.2)   # works, but

The lambda does the same thing. partial is preferable here for three reasons: it makes the intent (specialising a function) explicit, it keeps a useful repr showing what was bound, and it avoids the late-binding trap that catches lambdas defined in a loop.

That last point is the practical one. A lambda in a loop captures the variable, so all the lambdas end up sharing its final value. partial captures the value at the moment it is called, so building specialised functions in a loop works correctly.

funcs = [partial(apply_tax, rate=r) for r in [0.05, 0.2]]   # each keeps its own rate

Where it is genuinely useful

The best use is adapting a function to an interface that expects fewer arguments: a callback, a map, a sort key, or a pandas apply.

df["amount"].apply(partial(apply_tax, rate=0.2))

It also helps when configuring a function once and passing it around, so the configuration lives in one place rather than being repeated at every call site.

Positional versus keyword

partial fills positional arguments from the left, which is easy to get wrong on a function with several parameters.

partial(apply_tax, 100)      # fixes AMOUNT, not the rate!

Binding by keyword (rate=0.2) is unambiguous and survives the function's parameters being reordered, so prefer it unless you have a good reason not to.

Reading the result

A partial object shows what it wrapped, which is helpful when debugging.

print(with_vat)   # functools.partial(<function apply_tax ...>, rate=0.2)

A lambda shows only <lambda>, telling you nothing.

The honest caveat

For a one-off, a lambda is perfectly acceptable and shorter to read for many people. partial earns its place when you are creating several specialised versions, building them in a loop, or passing them somewhere they will be inspected or reused. Choose whichever makes the intent clearest to the next reader, and stay consistent within a codebase.

Need this solved on your own data?

The library is free and always will be. When the problem is bigger than an answer, we take on the work.

Start a project