How do I fix some arguments of a function in Python?
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.