
Every once in a while, you’ll find yourself writing one-line functions. Sometimes, these functions have default arguments or keyword arguments.
Pulling from Adam Johnson’s post of Django use cases of partial, he demonstrates that you can refactor a field if it’s being re-used across multiple models:
from django.db import models
class Book(models.Model):
created_at = models.DateTimeField(
default=timezone.now,
help_text="When this instance was created.",
)Notice that each Book model that’s created has arguments default and help_text?
Imagine each time you wanted to include the created_at field for different models, like Post or Magazine, or whatever needed the created_at field, you’d have to explicitly write it out:
from django.db import models
class Post(models.Model):
created_at = models.DateTimeField(
default=timezone.now,
help_text="When this instance was created.",
)
class Magazine(models.Model):
created_at = models.DateTimeField(
default=timezone.now,
help_text="When this instance was created.",
)This is where partial functions and partial methods from functools comes into play. It’s a very niche and not-very-well-known tool the standard library has to offer. Instead of having to repeat the code, you can define it as a partial and it’ll carry these default arguments through:
from django.db import models
CreatedAtField = partial(
models.DateTimeField, # The original function
default=timezone.now,
help_text="When this instance was created.",
)
class Book(models.Model):
created_at = CreatedAtField()
class Post(models.Model):
created_at = CreatedAtField()
class Magazine(models.Model):
created_at = CreatedAtField()What is a partial function?
A partial function allows us to take an existing function or method, supply some of its arguments in advance, and get back a function that only needs the remaining arguments.
In the example above, we’ve “pre-supplied” each argument with a default argument - default = timezone.now and help_text = “When this instance was created”.
At any point, we can modify these arguments to fit our model:
class DeletedBook(models.Model):
originally_created_at = CreatedAtField(
help_text = "When the Book instance was originally created."
)Can I use this in my own class?
Unfortunately, no. But, that is when partialmethod comes into play! Methods need to bind self automatically when called through an instance; this is part of how Python’s descriptor protocol works:
from functools import partialmethod
class HTTPClient:
def request(self, method, endpoint):
return f"{method} {endpoint}"
get = partialmethod(request, method = "GET")
post = partialmethod(request, method = "POST")
client = HTTPClient()
client.get(endpoint = "/users") # GET /users
client.post(endpoint = "/users/article") # POST /users/articleBasically, you’ll use partialmethod inside class bodies (for methods), partial everywhere else (for functions).
Okay… so why is this important to know?
It’s hard to argue “this is something that’s extremely important to know”, because it’s not something that’s beginner-friendly from a syntax perspective.
However, for those who have been working with Python for a while, it makes your code much more elegant, easier to read, and more light-weight.
For instance, if you’re building a CLI application that wraps git, kubectl, and aws for whatever reason, you may want to look at using partial if you’re wiring together a bunch of commands:
from functools import partial
import subprocess
run = partial(
subprocess.run, check=True,
text=True, capture_output=True
)
def current_branch():
return run(
["git", "rev-parse", "--abbrev-ref", "HEAD"]
).stdout.strip()
def latest_commit():
return run(
["git", "log", "-1", "--pretty=%H"]
).stdout.strip()
def changed_files():
return run(
["git", "diff", "--name-only"]
).stdout.splitlines()Happy coding!
📧 Join the Python Snacks Newsletter! 🐍
Want even more Python-related content that’s useful? Here’s 3 reasons why you should subscribe the Python Snacks newsletter:
Get Ahead in Python with bite-sized Python tips and tricks delivered straight to your inbox, like the one above.
Exclusive Subscriber Perks: Receive a curated selection of up to 6 high-impact Python resources, tips, and exclusive insights with each email.
Get Smarter with Python in under 5 minutes. Your next Python breakthrough could just an email away.
You can unsubscribe at any time.
Interested in starting a newsletter or a blog?
Do you have a wealth of knowledge and insights to share with the world? Starting your own newsletter or blog is an excellent way to establish yourself as an authority in your field, connect with a like-minded community, and open up new opportunities.
If TikTok, Twitter, Facebook, or other social media platforms were to get banned, you’d lose all your followers. This is why you should start a newsletter: you own your audience.
This article may contain affiliate links. Affiliate links come at no cost to you and support the costs of this blog. Should you purchase a product/service from an affiliate link, it will come at no additional cost to you.

