Python alternative to reduce()

PythonFunctional Programming

Python Problem Overview


There is a semi-famous article written by Guido himself hinting that reduce() should go the way of the dodo and leave the language. It was even demoted from being a top-level function in Python 3 (instead getting stuffed in the functools module).

With many other functional programming staples (map, etc) common clear alternatives are available. For example, most of the time a map() is better written as a list comprehension.

What I'd like to know is if there is a similar "more pythonic" alternative to the reduce function. I have a bit of a functional programming background (ML in particular), so reduce() often springs to my mind when thinking of a solution, but if there's a better way to do them (short of unrolling a reduce call into a for loop) I'd like to know.

Python Solutions


Solution 1 - Python

As Guido's linked article says, you should just write an explicit for loop if you want to avoid reduce(). You can replace the line

result = reduce(function, iterable, start)

by

result = start
for x in iterable:
    result = function(result, x)

Solution 2 - Python

What I'd like to know is if there is a similar "more pythonic" alternative to the reduce function.

Yes and no. It depends upon the use case.

In the linked article Guido suggests that most but not all reductions ought to be written as loops. There are limited circumstances in which he sees reduce as being applicable.

> So in my mind, the applicability of reduce() is pretty much limited to > associative operators, and in all other cases it's better to write out > the accumulation loop explicitly. > > There aren't a whole lot of associative operators. (Those are > operators X for which (a X b) X c equals a X (b X c).) I think it's > just about limited to +, *, &, |, ^, and shortcut and/or.

Solution 3 - Python

The two-line alternative for python>=3.8

result = your_array[0]
[result := your_func(result, x) for x in list_of_matrices[1:]]

Example for calculating the Kronecker product:

list_of_matrices = [
   [[1,2],
    [3,4]],

   [[5,6,2],
    [7,2,1]],

   [[9,8,7],
    [1,4,5],
    [8,2,1],
    [1,1,2]],
    ]*4

result_reduce = reduce(np.kron, list_of_matrices) 

result_walrus = list_of_matrices[0]
[result_walrus := np.kron(result_walrus, x) for x in list_of_matrices[1:]]

print((result_walrus == result_reduce).all())

Output:

True

Timings:

Reduce 30 times: 10.39 sec.
Walrus 30 times: 10.37 sec.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAdam ParkinView Question on Stackoverflow
Solution 1 - PythonSven MarnachView Answer on Stackoverflow
Solution 2 - PythonkkurianView Answer on Stackoverflow
Solution 3 - PythonvoldrView Answer on Stackoverflow