Partial objects are loosely related to the concept of partial functions in mathematics. A prtial function is a generalization of a mathematical function in a way that isn't forced to map every possible input value (domain) to its results. In Python, partial objects can be used to slice the possible input domain of a given function by setting some of its arguments to a fixed value.
In the previous sections, we used the x ** 2 expression to get the square value of x. Python provides a built-in function called pow(x, y) that can calculate any power of any number. So, our lambda x: x ** 2 function is a partial function of the pow(x, y) function, because we have limited the domain values for y to a single value, 2. The partial() function from the functools module provides an alternative way to easily define such partial functions without the need for lambda functions, which can sometimes become unwieldy.
Let's say that we now want to create a slightly different partial function out of pow(). Last time, we generated squares of consecutive numbers. Now, let's narrow the domain of other input arguments and say we want to generate consecutive powers of the number two – so, 1, 2, 4, 8, 16, and so on.
The signature of a partial object constructor is partial(func, *args, **keywords). The partial object will behave exactly like func, but its input arguments will be pre-populated with *args (starting from the leftmost) and **keywords. The pow(x, y) function does not support keyword arguments, so we have to pre-populate the leftmost x argument as follows:
>>> from functools import partial
>>> powers_of_2 = partial(pow, 2)
>>> powers_of_2(2)
4
>>> powers_of_2(5)
32
>>> powers_of_2(10)
1024
Note that you don't need to assign your partial to any identifier if you don't want to reuse it. You can successfully use it to define one-off functions in the same way that you would use lambda functions. The following example shows how various functions that have been presented in this chapter can be used to create a simple generator of infinite powers of the number two without any explicit function definition:
from functools import partial
from itertools import count
infinite_powers_of_2 = map(partial(pow, 2), count())
Let's take a look at generator expressions in the next section.