python-course.eu

11. Currying in Python

By Bernd Klein. Last modified: 08 Mar 2024.

General Idea

Curry mit Currying

In mathematics and computer science, currying is the technique of breaking down the evaluation of a function that takes multiple arguments into evaluating a sequence of single-argument functions. Currying is also considered to be a design pattern. Currying is also used in theoretical computer science, because it is often easier to transform multiple argument models into single argument models.

Live Python training

instructor-led training course

Enjoying this page? We offer live Python training courses covering the content of this site.

See our Python training courses

See our Machine Learning with Python training courses

Origin of the Name

The "Curry" in "Currying" has nothing to do with the spicy curry powder, even though it can make your Python code more spicy. The name is a reference to the logician and mathematician Haskell Brooks Curry, and he is quoted in "THE KLEENE SYMPOSIUM", (Proceedings of the Symposium held June 18-24, 1978 at Madison, Wisconsin. U.S.A.):

Some contemporary logicians call this way of looking at a function “currying”, because I made extensive use of it; but Schonfinkel had the idea some 6 years before I did.

This is why there is also - though seldomly - the name "Schönfinkelisation" being used. There are even further roots of the concept going back to the end of the 19th century and the mathematician Gottlob Frege.

Currying Functions

Currying is the technique of breaking down the evaluation of a function that takes multiple arguments into evaluating a sequence of single-argument functions.

In mathematical notation it looks like this: If we have a function $f$ which takes $n$ arguments, we can 'replace' it by a composition of $n$ functions $f_1, f_2, \ldots f_n$ where each takes only one argument:

$$let x = f(a_1, a_2, a_3)$$

we will get the same value x as if we call:

$$f_2 = f_1(a_1)$$
$$f_3 = f_2(a_2)$$

and

$$x = f_3(a_3)$$

An example implemented in Python could look like this:

def f(a1, a2, a3):
    return a1 * a2 * a3

def f1(a1):
    def f2(a2):
        def f3(a3):
            return f(a1, a2, a3)
        return f3
    return f2
for i in range(1, 10):
    print(f(i, i+1, i+2), f1(i)(i+1)(i+2))

OUTPUT:

6 6
24 24
60 60
120 120
210 210
336 336
504 504
720 720
990 990

Live Python training

instructor-led training course

Enjoying this page? We offer live Python training courses covering the content of this site.

Upcoming online Courses

See our Python training courses

See our Machine Learning with Python training courses

Example BMI

We illustrate this with the function BMI, which we had used in our chapter on functions. We write a curried version of BMI:

def BMI(weight, height):
    return weight / height**2

def bmi_curried(height):
    def bmi_weight(weight):
        return BMI(weight, height)
    return bmi_weight
bmi_curried(1.76)(72)

OUTPUT:

23.243801652892564

Using partial

The function partial of the module functools of Python allows you to create partially applied functions. A partially applied function is a new function that is derived from an existing function by fixing a certain number of arguments in advance. The result is a function that can be called with the remaining arguments. We can use it for the commposition of functions.

We demonstrate the way of working in the following examples:

from functools import partial

def f(a1, a2):
    return a1 * a2 

partial(f, 3)(4)

OUTPUT:

12
from functools import partial

def f(a1, a2, a3):
    return a1 * a2 * a3

partial(f, 3, 2)(4)

OUTPUT:

24
partial