Skip to main content

Exploring functools.partial

·2 mins

Introduction
#

The goal of today’s post is to dig into the Python’s functools.partial object.

Partial Basics
#

Let’s start by importing partial from Python’s built-in functools.

>>> from functools import partial

Next, we define a simplistic multiply method and a times_two partial object which fixes the multiplier to always be 2.

>>> def multiply(a: int, b: int) -> int:
...     return a * b

>>> times_two = partial(multiply, b=2)

>>> times_two(3)
6

When inspecting the __name__ and __doc__ fields that regular Python methods always provide, we notice that for partial objects __name__ does not exists and __doc__ is set to some generic partial object default. So to have sensible values for the two fields, we have to set those ourselves.

>>> times_two.__name__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'functools.partial' object has no attribute '__name__'. Did you mean: '__ne__'?

>>> times_two.__name__ = 'times_two'
>>> times_two.__name__
'times_two'

>>> times_two.__doc__
'partial(func, *args, **keywords) - new function with partial application\n    of the given arguments and keywords.\n'

>>> times_two.__doc__ = 'Multiply the given value times two.'
>>> times_two.__doc__
'Multiply the given value times two.'

When printing our times_two partial we get the name of the class together with a reference to the original method and the arguments that we’ve fixed for our partial.

>>> times_two
functools.partial(<function multiply at 0x101358900>, b=2)

We can also get those latter two explicitly, using the .func and keywords fields of partial.

>>> times_two.func
<function multiply at 0x101358900>

>>> times_two.keywords
{'b': 2}

If we had used partial with non-keyword arguments (like partial(multiply, 2), which would’ve set a to 2), those values would show up in the .args field. Since we’ve only used keyword arguments however, args will be an empty tuple in our case.

>>> times_two.args
()

Partial With Types
#

If we ask Python for the type of the partial, it will simply tell us it’s a functools.partial object.

>>> type(times_two)
<class 'functools.partial'>

And while we can get the argument names with their types as well the return type from a regular Python method using <method_name>.__annotations__, this dunder method is not provided for partial objects.

>>> times_two.__annotations__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'functools.partial' object has no attribute '__annotations__'

However, we can retrieve the same output using the simple dict comprehension below.

>>> {k: v for k, v in times_two.func.__annotations__.items() if k not in times_two.keywords}
{'a': <class 'int'>, 'return': <class 'int'>}
Florian Schäfer
Author
Florian Schäfer
Welcome to my website where you can read my blog or learn something about me.