What is the 'reduce' function in Python?

5

In what cases is it useful and how can I use the reduce function?

    
asked by anonymous 17.04.2018 / 04:18

1 answer

9

The reduce function, available in the built-in module functools , serves to "reduce" an iterable (as a list) to a single value.

It is a somewhat more common paradigm in functional languages, but it is also very useful in imperative / object-oriented languages such as Python.

But how do you "reduce" a list?

Suppose you have a minha_lista list, which only contains numbers, and that you want the multiplication result among all those numbers. One of the ways to do this is with a for:

# Queremos 2 * 4 * 5 * 2, que é igual a 80
minha_lista = [2, 4, 5, 2]

produto_total = 1
for numero in minha_lista:
     produto_total *= numero

print(produto_total)  # 80

This works, but it can also be done with reduce :

from functools import reduce

minha_lista = [2, 4, 5, 2]

def mult(x, y):
    return x * y

produto_total = reduce(mult, minha_lista)
print(produto_total)  # 80

Or, equivalently but a bit more concise, with a lambda function (which is nothing more than a function defined in a single expression / line):

from functools import reduce

minha_lista = [2, 4, 5, 2]

produto_total = reduce(lambda x, y: x * y, minha_lista)
print(produto_total)  # 80

So what's going on there? If we take a look at "slow motion", what happens is this:

  • reduce receives as function argument applied the function mult (or lambda, in the second case)
  • reduce receives as iterable the minha_lista
  • reduce considers as x and y , respectively, the first two elements of minha_lista : 2 and 4
  • reduce applies to x and y the mult function, which multiplies one by the other: in 2 * 4 , the result is 8.
  • The result of applying the function (our 8) becomes x , and the next element unprocessed (5, third element of our list) becomes y
  • The mult function is applied to x and y : 8 * 5 returns 40 , and this returned value becomes our new x
  • The mult function is last applied to x and the last element in our list, 2 . 40 * 2 returns us 80

  • Since there are no more elements to apply the function, reduce returns the final result: 80, as expected.

  • In short, the function applies another function sequentially and cumulatively to a list (iterator), and "reduces" the list to a single final result.

    Another didactic example is to calculate the minimum value of a list:

    from functools import reduce
    
    minha_lista = [2, 4, 5, 2, 1]
    
    def achar_minimo(x, y):
        if x < y:
            return x
        else:
            return y
    
    minimo = reduce(achar_minimo, minha_lista)
    print(minimo)  # 1
    

    In this case, the first argument x is used to store the smallest value seen, and it is compared to the other y values in the list.

    I say this example is didactic because there is already an equivalent function in Python: the min . Still, I think the example is cool to give another idea of the power of reduce .

    In addition to the above, reduce also accepts an optional third argument, initial_value . As the name implies, this argument can be given as the initial value, and is in effect the same thing as putting this value at the beginning of your list.

    These examples are simple and may seem silly, but as the functions applied become more complex, using reduce may be a good way to decrease the size of the code and make it clearer. Either way, it's a good tool to have.

        
    17.04.2018 / 04:18