Have you ever calculated your potential weekly income by multiplying a variety of numbers by 40?
What about using the same opening lines while inserting different names in addressing a letter to a variety of recipients?
Developers often face the issue of supplying a variety of inputs to a single object. This can be tedious without the right tooling, but Python luckily has partial functions to speed the process along.
Below you’ll learn about partial functions, including how to create them and how they’re applied in everyday Python programming.
What is a Partial Function?
Using partial functions is a component of metaprogramming in Python, a concept that refers to a programmer writing code that manipulates code.
You can think of a partial function as an extension of another specified function. A partial function has the same functionality of the specified function, but with pre-filled values for a certain number of arguments. As long as you employ partial functions properly — creating them only when you’ll need to use certain arguments over and over again — their use will help keep your code concise and reusable.
Here’s an example of a function that multiplies two numbers together:
This is a function we can use for many purposes. But say that we’re calculating our annual expenses and have an average monthly expense for three categories: clothing, food, and housing. Why should we repeatedly plugin 12 as one of our numbers (months of the year) when we can create a partial function that has 12 as a fixed argument? Let’s look at how to implement such a function.
Implementing a Partial Function
Before coding out our first partial function, we’ll need to import the functools library, which allows us to use higher-order functions like partial():
When called, partial() allows the program to output a function object resembling the original function with a fixed argument(s) passed into it. Recall that we’ll want to use multiply() as our function and 12 as our fixed integer. We’ll need to pass both into partial(), noting, however, that the input function is always supplied first:
The program will forward calls of the partial times_twelve to the multiply() function with a constant argument of x as 12. You may supply as many fixed arguments to your partial as there are parameters in your original function, but note that doing so will result in a function that takes no arguments and is fixed:
While still a partial function, it’s not that useful.
In case we want to “skip” a parameter in the original function, we can specify what variables we’re fixing, using keywords:
For our purposes, this doesn’t matter because multiplication treats x and y the same. But in cases where the arguments would be treated differently (e.g., a base and an exponent) using keywords would make a difference.
Now that we’ve created our partial function, let’s call it. Let’s say you spend $51 per month on your gym membership:
Now you know you spend $612 a year to exercise at your local gym, and you didn’t need to write a whole new function or plug two arguments into your multiply() function to perform the calculation.
Before we move on, note that just as partial functions can take a custom function like multiply() as input, they can also take object methods as their first parameter. For example, we’ll pass the list method insert() to a partial function and pre-fill index 0 as insert()’s first argument. We’ll then call our partial function add_veggies with the item we want to insert, which is traditionally insert()’s second argument:
Now let’s look at alternative ways to create the same functionality as partial functions but without using the functools library.
Can You Create a Partial Function Without Functools?
Using functools.partial() is easily the most convenient and recommended way to implement a partial function, but it’s not your only option. We can also use the def keyword and lambda functions to do so. Here, we create the same times_twelve functionality, but using a traditional function definition:
We don’t recommend this method because defining a new “regular” function diminishes readability and conciseness, but understanding this approach will give you a good understanding of how Python treats partial functions. From this definition, you can see that a partial function is a new function that returns the results of an old function with a fixed parameter. That’s it! Note for later that a partial function returns another function.
We can also use a lambda function to simulate a partial function:
While creating a new function definition simulates functools.partial(), lambdas use late binding for the arguments they receive and thus work a little differently under the hood. Besides, functools.partial() in Python was designed for the exact purpose of creating partial functions, so why not take advantage of it?
Now, let’s look at some partial function applications to see how they’re used in everyday Python programming.
Applications of Partial Functions
Web development gives plenty of opportunity for partial functions to shine — just think of all the circumstances in which you’d want to “fix” a certain factor in your browsing. You might prefer to search for flights from a fixed location, view clothing prices in a given currency or set a max price for your Airbnb filter. When creating a website, a developer might create partial functions to make all that possible for you.
Since Python is the foremost language for data science, it’s only fitting that partial functions have a place in data analytics applications. In the data modeling context, for example, if you want to use a particular model in a general function, you can pass it in as the fixed argument to a partial function:
But it’s not only data analysis that benefits from partial functions. When it comes to data parsing, you can use them to do such tasks as read files by fixed-size records instead of line-by-line. The third example in this expert analysis illustrates the technique.
Are there any cases where you’d want to avoid using partial functions? Yes, if you’re not going to be using a fixed argument heavily, or if creating a partial function would violate code conciseness and reusability principles. In these cases, just plug your argument(s) into the specified “regular” function.
Passing Partial Functions to Functions
Recall from our previous example that, under the hood, a partial function returns another function. In that example, our partial function returned multiply(12, y). Because all functions in Python are first-class citizens, you can use them as you would any other object, assigning them to variables or passing them as input to other functions. Accordingly, you can take the output function of a partial function and feed it to other functions. Let’s look at the implications.
First, let’s see what happens when you pass a partial function as the first parameter to another partial function. We’ll use our partial function times_twelve as an argument to a second partial function:
Because times_twelve has only one available variable, the integer 3 will “take” that variable, so the call to thirty_six will always result in 36. However, as long as you have available variables in partial functions, you can keep passing them as arguments to other partial functions.
Per the definition of map(), this results in the program applying the partial function to every input in a list and creating a new list as a result.
Now that you know all about partial functions, including how to create them, what they’re used for and how to pass them to other functions, you’re one step closer to becoming a Python programmer.
But beyond partial functions, you’ll need to master various other fundamentals to acquire Python proficiency.
Sound interesting? We’ve got you covered with our Introduction to Python Programming course.