Python's functools.partial() Lets You Pre-Fill A Function
An exploration of partial() and partialmethod() in functools
Don't you love it when you need to fill in a form and some fields are already filled in?
There are times when you're coding in Python when you need to use a function with the same arguments over and over again. If only you could pre-fill those arguments, like the form!
As it happens, you can. Python's functools.partial()
enables you to "pre-fill" some arguments in a function. In this article, I'll explore how to use partial()
. I'll also look at its close relative, partialmethod()
.
A quick 'author's note': Some of the articles I'll publish on The Python Coding Stack—such as this one—will be focused deep dives into a specific Python function or class, either from the standard module or from key third-party modules such as NumPy or Matplotlib. Readers will fall into one of three categories: 1. You may already know everything about this topic. 2. You may be entirely new to the topic. Or... 3. You may have used the function or class but haven't yet explored it fully. When I write deep dives, I'm usually in the third category trying to learn more about these tools myself.
Using Python's functools.partial()
: Modifying print()
When you use the built-in print()
function, the last character printed out is the newline character by default. Let's assume you'd like to use print()
often in a program, but you don't want your output to be on a new line each time. You can use the optional argument end
in print()
. I'll use a short example to demonstrate this:
The output of this code is shown below:
Tails Tails Heads Heads Tails Heads Tails Heads Tails Heads
This code "flips a coin" by generating a random number between 0 and 1 using random.random()
and printing "Heads"
if the number is lower than 0.5 and "Tails"
if it's larger.
The second argument in the two print()
calls replaces the newline character, which is the last character by default, with a space. If you omit this keyword argument, each print()
will start a new line.
If you need to use this often in a program, you may wish to have a version of the print()
function with end=" "
pre-filled. You can use functools.partial()
for this:
The output is similar to the previous example:
Heads Tails Tails Tails Heads Heads Tails Tails Tails Tails
partial()
is part of the functools
module. You call functools.partial()
with two arguments:
The name of the function you want to "pre-fill", which is
print
The keyword argument
end=" "
. This is also a valid keyword argument inprint()
partial()
returns an object you call print_on_line
. You can use this object to replace the print()
function, as we've done in the if..else
blocks in this code. The call to print_on_line("Heads")
is equivalent to print("Heads", end=" ")
. We'll look at what's happening in more detail shortly.
What Does partial()
Return?
The object returned by functools.partial()
looks and behaves like a function. It's an object of type partial
. We'll continue exploring this in a Console/REPL session:
This confirms that print_on_line
is a functools.partial
object and that it's callable. This is why we can use it in the same way as the function we're "pre-filling".
The partial
object has three attributes:
.func
.args
.keywords
Let's see their values in this example:
The .func
attribute contains a reference to the built-in print
function. This is the pre-existing function we're building on. The .args
attribute shows any positional arguments passed to partial()
. In this case, there aren't any since the only additional argument is a keyword argument. We wrote the argument as the named keyword argument end=" "
. If we wrote just " "
instead, the argument would be a positional argument.
We'll look at another example later that will include positional arguments. You can read more about positional and keyword arguments in this article I wrote in the pre-substack era!
The final attribute, .keywords
, shows any keyword arguments passed to partial()
. This is a dictionary with the key "end"
with the empty string " "
as its value.
Any positional and keyword arguments passed to partial()
are automatically passed to the original function. This is why print_on_line("Heads")
is equivalent to print("Heads", end=" ")
.