Partials

Partials really help using functional concepts in Python. Using a partial just means executing a function with a partial argument list, which return another function, with the partials arguments alerady "filled".

Can make classes that are just used as attribute containers obsolete. I find this very appealing.


In [12]:
from functools import partial

In [8]:
def greet(greeting, name):
    return "{0}! {1}".format(greeting, name)

The following is the standard way of calling this function. I want to greet Klaus with a simple "Hello". Thus, I add two arguments to the function.


In [21]:
greet("Hello", "Klaus")


Out[21]:
'Hello! Klaus'

Now I want to build a function that always greets with the phrase "Good evening". I could solve this with a class or just always use two arguments. Or I could define a partial function.


In [34]:
good_evening_greet = partial(greet, "Good evening")

In [23]:
good_evening_greet("Klaus")


Out[23]:
'Good evening! Klaus'

In [24]:
good_evening_greet("Engelbert")


Out[24]:
'Good evening! Engelbert'

good_evening_greet itself is a function:


In [30]:
good_evening_greet


Out[30]:
<functools.partial at 0x103aed998>

This nice little tool allows me to create different functions from a function that have some values already embedded into them. This approach is very similar to the closure appraoch from lesson one, but with one important distinction:

I don't have to think about the closure-ness at the time I am writing the greet function.

The closurable "greet" function would have to look like this:


In [25]:
def closure_greet(greeting):
    def named_greet(name):
        return "{0}! {1}".format(greeting, name)
    return named_greet

In [28]:
evening_closure_greet = closure_greet("Good evening my dear closure")

In [29]:
evening_closure_greet("Klaus")


Out[29]:
'Good evening my dear closure! Klaus'

Note how it wouldn't be possible to embed a pre-fixed name into this construct, because the order of nesting does not allow this. Using a partial, this is very simple:


In [32]:
greet_queen_mother = partial(greet, name="Queen Elizabeth the Queen Mother")

In [33]:
greet_queen_mother("Nice to see you")


Out[33]:
'Nice to see you! Queen Elizabeth the Queen Mother'

I could even build on good_evening_greet to wish the Queen Mother a good evening:


In [35]:
good_evening_queen_mother = good_evening_greet("Queen Elizabeth the Queen Mother")

In [36]:
good_evening_queen_mother


Out[36]:
'Good evening! Queen Elizabeth the Queen Mother'

Thus, I do find partials a very neat and flexible way to enable a very important concept of FP. Note how there is no global state introduced and no variables needed to be set.