written by Eric J. Ma on 2019-03-22 | tags: python hacks tips and tricks data science productivity coding
If you’ve done Python programming for a while, I think it pays off to know some little tricks that can improve the readability of your code and decrease the amount of repetition that goes on.
One such tool is functools.partial
. It took me a few years after my first introduction to partial
before I finally understood why it was such a powerful tool.
Essentially, what partial
does is it wraps a function and sets a keyword argument to a constant. That’s it. What do we mean?
Here’s a minimal example. Let’s say we have a function f
, not written by me, but provided by someone else.
def f(a, b): result = # do something with a and b. return result
In my code, let’s say that I know that the value that b
takes on in my app is always the tuple (1, 'A')
. I now have a few options. The most obvious is assign the tuple (1, 'A')
to a variable, and pass that in on every function call:
b = (1, 'A') result1 = f(a=1, b=b) # do some stuff. result2 = f(a=15, b=b) # do more stuff. # ad nauseum N = # set value of N resultN = f(a=N, b=b)
The other way I could do it is use functools.partial
and just set the keyword argument b
to equal to the tuple directly.
from functools import partial f_ = partial(f, b=(1, 'A'))
Now, I can repeat the code above, but now only worrying about the keyword argument a
:
result1 = f_(a=1) # do some stuff. result2 = f_(a=15) # do more stuff. # ad nauseum N = # set value of N resultN = f_(a=N)
And there you go, that’s basically how functools.partial
works in a nutshell.
Now, where have I used this in real life?
The most common place I have used it is in Flask. I have built Flask apps where I need to dynamically keep my Bokeh version synced up between the Python and JS libraries that get called. To ensure that my HTML templates have a consistent Bokeh version, I use the following pattern:
from bokeh import __version__ as bkversion from flask import render_template, Flask from functools import partial render_template = partial(render_template, bkversion=bkversion) # Flask app boilerplate app = Flask(__name__) @app.route('/') def home(): return render_template('index.html.j2')
Now, because I always have bkversion
pre-specified in render_template
, I never have to repeat it over every render_template
function call.
@article{
ericmjl-2019-functools-partial,
author = {Eric J. Ma},
title = {Functools Partial},
year = {2019},
month = {03},
day = {22},
howpublished = {\url{https://ericmjl.github.io}},
journal = {Eric J. Ma's Blog},
url = {https://ericmjl.github.io/blog/2019/3/22/functools-partial},
}
I send out a newsletter with tips and tools for data scientists. Come check it out at Substack.
If you would like to sponsor the coffee that goes into making my posts, please consider GitHub Sponsors!
Finally, I do free 30-minute GenAI strategy calls for teams that are looking to leverage GenAI for maximum impact. Consider booking a call on Calendly if you're interested!