97% of Python Projects Could Be Cleaner With partial() | by Jaume Boguñá - Freedium
97% of Python Projects Could Be Cleaner With partial()
How one built-in tool can save you lines of code and mental energy
androidstudio · April 17, 2025 (Updated: April 17, 2025) · Free: No
I remember the first time I came across functools.partial
— I had no clue what it did, and honestly, I skipped over it like it was some obscure trick I'd never need.
Fast forward a few real-world projects later, and I can tell you this: partial()
has made my code cleaner, more reusable, and even more fun to write.
Partial functions let you lock in some arguments, so you don't repeat yourself every time. It's like creating a custom version of a function with minimal effort.
In this post, I'll show you how partial()
works, how I use it in real code, and why it might just be the cleanest feature you're not using yet.
Let's dive in.
Partial Functions Syntax (The Basics)
When I first learned about partial()
, I was surprised by how simple the syntax actually is.
All you need is to import it from functools
, and then you can "lock in" one or more arguments to create a new version of your function:
from functools import partial
# Define a regular function
def func(arg1, arg2, arg3):
# Do something
pass
# Create a partial function by fixing some arguments
partial_func = partial(func, fixed_arg1, fixed_arg2)
# Now call it with the remaining arguments
result = partial_func(arg3)
It's that easy. The partial function behaves just like the original — except with fewer arguments to worry about.
Once I saw this in action, I started using it to simplify everything from callbacks to repeated config-heavy functions.
Let me show you a real use case next.
Real Example 1: My BMI Calculator
Here's when partial()
really clicked for me — I was tracking my weight over time and got tired of retyping my height every time I calculated my BMI.
So I used functools.partial
to lock in my height once, and just pass in the changing weight:
from functools import partial
def calculate_bmi(height: float, weight: float) -> str:
bmi = weight / (height ** 2)
return f"Your Body Mass Index (BMI) is {bmi:.2f}."
# Set my height once and reuse the function
bmi_for_my_height = partial(calculate_bmi, height=1.75)
# Track weight changes over time
print(bmi_for_my_height(weight=63)) # 01/01/2024
# → Your Body Mass Index (BMI) is 20.57.
print(bmi_for_my_height(weight=66)) # 01/06/2024
# → Your Body Mass Index (BMI) is 21.55.
Just one line with partial()
and I had a custom BMI calculator ready to go.
That's the kind of small win that makes coding feel a little magical.
Real Example 2: Weather Report with City Locked In
I used to pass the city name every time I generated a weather report. Then I realized… why not fix it once?
Here's how I did it with partial()
:
from functools import partial
def weather_report(city: str, temp: int, rain: bool) -> str:
return f"""Temperature in {city} is {temp}ºC.
It is {'raining' if rain else 'not raining'}."""
# Regular usage
print(weather_report('Lima', 17, True))
# → Temperature in Lima is 17ºC.
# → It is raining.
# Lock in the city as 'Madrid'
madrid_weather_report = partial(weather_report, city="Madrid")
# Now just update the weather
print(madrid_weather_report(temp=24, rain=False))
# → Temperature in Madrid is 24ºC.
# → It is not raining.
This is perfect when you're dealing with repeated values — just fix them once, and leverage the shortcut.
Using partial() with Built-In Functions
One of the coolest things? You can use partial()
with built-in functions too.
I wanted my print()
calls to use newlines instead of spaces — without setting sep="\n"
every time. So I did this:
from functools import partial
# Create a version of print with a custom separator
print_with_sep = partial(print, sep="\n")
# Now this prints each item on a new line
print_with_sep("Name: Jaume", "Age: 25", "Pet: Mimi")
# → Name: Jaume
# → Age: 25
# → Pet: Mimi
No wrappers, no extra functions — just one line, and done. This kind of tweak makes your code neater and more readable instantly.
Partial Functions vs. Lambda: Which One to Use?
After I got comfortable with partial()
, I started comparing it to another common tool: lambda functions. Both allow you to create smaller, more specialized functions, but they each have their strengths.
Partial Functions
-> What it does: Pre-fills arguments for an existing function.
-> Syntax: partial(existing_func, fixed_args)
-> Pros:
- Tied to an existing function — keeping code structured and readable.
- Great for reusing and simplifying existing functions.
- More explicit and easier to read, especially in larger projects.
-> Cons:
- Slight overhead due to function wrapping.
-> Example:
from functools import partial
def power(base, exponent):
return base ** exponent
# Regular function call for squaring
print(power(5, 2))
# → 25
# Using partial to create a new function for squaring
square = partial(power, exponent=2)
print(square(5))
# → 25
Lambda Functions
-> What it does: Creates anonymous, inline functions.
-> Syntax: lambda args: expression
-> Pros:
- Super lightweight and flexible for quick, one-off functions.
- Excellent for short-term, ad-hoc operations.
-> Cons:
- Can get messy and hard to read when functions grow in complexity.
-> Example:
# Using a lambda function to square a number
square = lambda base: base ** 2
print(square(5))
# → 25
So, which to use?
partial()
: I use it when I want to reuse existing functions with certain arguments fixed, especially when readability and structure matter.lambda
: I turn to lambdas for quick, inline tasks when I don't need a full function definition.
Both are useful, but I find myself leaning towards partial()
for more complex, reusable logic. How about you? Do you prefer one over the other for your coding style?
Advantages of Partial Functions
Now that I've been using partial()
, I can't ignore the major benefits it brings to the table. Here's why it's been a game-changer for my code:
1. Reusability
With partial()
, I can reuse existing functions but lock in some of the arguments, creating specialized versions. No need to retype code or redefine functions every time — just call the partial function with the remaining parameters.
2. Code Simplification
How many times have you had to pass the same arguments around? partial()
eliminates that. I can fix certain values in one place, which makes future calls simpler and cleaner.
3. Readability
By locking in arguments, the function calls become more readable. It's immediately clear what the function does and which arguments are "preset" — reducing the cognitive load for anyone reading the code.
4. Customization
It's incredibly easy to customize a general-purpose function. I just set the fixed arguments once and get a tailored version of that function. It's like building a custom tool for your project with minimal effort.
5. Modularity
partial()
helps break down complex functions into smaller, reusable components. Instead of repeating logic, I can focus on specific tasks, creating modular chunks of code that are easy to maintain.
In short, partial functions let me work smarter, not harder. Once you start using them, you'll wonder how you ever got by without them.
So if you haven't yet explored partial()
, give it a try. It might just become your new best friend in the world of Python functions.
Feel free to drop a comment if you have any questions or thoughts on using partial functions in your projects. I'd love to hear how you're using them!