# Python reduce and accumulate total guide

## Python reduce function

Python’s reduce()
implements a mathematical technique commonly known as folding
or **reduction**. You’re doing a fold or reduction when you reduce a list of items to a single cumulative value. Python’s reduce()
operates on any iterable
(not just lists) and performs the following steps:

`Apply a function`

(or callable) to the**first two items**(default) in an iterable and generate a partial result.`Use that partial result`

, together with the third item in the iterable, to generate another partial result.`Repeat the process`

until the iterable is exhausted and then return a single cumulative value.

#### Python reduce function

Apply function of two arguments cumulatively to the items of iterable , from left to right, so as to reduce the iterable to a single value.[python doc]

```
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
```

The idea behind Python’s **reduce()** is to take an existing function, apply it cumulatively to all the items in an iterable, and generate a single final value. In general, Python’s **reduce()** is handy for processing iterables without writing explicit for loops. **Since reduce() is written in C, its internal loop can be faster than an explicit Python for loop**.

Python’s reduce() was originally a built-in function (and still is in Python 2.X ), but it was moved to functools.reduce() in Python 3.0 . This decision was based on some possible performance and readability issues.

In Python 3.X, if you need to use reduce(), then you first have to import the function into your **current scope** using an import statement
in one of the following ways:

**import functools**and then use fully-qualified names like**functools.reduce()**.**from functools import reduce**and then call**reduce()**directly.

```
functools.reduce(function, iterable[, initializer])
```

If the optional **initializer** is present, it is placed before the items of the iterable in the calculation, and serves as a default when the iterable is empty.

If initializer is not given and iterable contains only one item, the first item is returned.

#### find sum of iterable int with reduce

```
reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])
# output
# 15
```

#### Find the largest number in the iterable using reduce()

```
from functools import reduce
num1 = [15,12,30,4,5]
num2 = reduce(lambda x,y: x if x>y else y, num1)
print(num2)
# output
# 30
```

#### Using User-defined function in reduce()

```
from functools import reduce
def my_add(a, b):
result = a + b
print(f"{a} + {b} = {result}")
return result
numbers = [0, 1, 2, 3, 4]
reduce(my_add, numbers)
# output:
# 0 + 1 = 1
# 1 + 2 = 3
# 3 + 3 = 6
# 6 + 4 = 10
# 10
```

#### Iterable contains only one item, reduce() will return that item.

```
from functools import reduce
def sum1(x, y):
return x + y
num1 = [5]
num2 = reduce(sum1,num1)
print(num2)
# output
# 5
from functools import reduce
num1 = [15]
num2 = reduce(lambda x,y: x if x>y else y, num1)
print(num2)
# output
# 15
```

### python reduce initializer

```
functools.reduce(function, iterable[, initializer])
```

#### Initializer

The third argument to Python’s reduce(), called`initializer`

, is optional. If you supply a value to initializer, then **reduce()**will feed it to the first call of function as its

**first argument**. This means that the

**first call to function will use the value of**. After this, reduce() continues working with the subsequent items of iterable.

`initializer`

and the first item of iterable to perform its first partial computation```
from functools import reduce
def my_add(a, b):
result = a + b
print(f"{a} + {b} = {result}")
return result
numbers = [0, 1, 2, 3, 4]
reduce(my_add, numbers, 100)
# output
# 100 + 0 = 100
# 100 + 1 = 101
# 101 + 2 = 103
# 103 + 3 = 106
# 106 + 4 = 110
# 110
```

## Python accumulate function

```
itertools.accumulate(iterable[, func, *, initial=None])
```

#### Python accumulate

Make an iterator that returns accumulated sums, or **accumulated results** of other **binary functions** (function with exactly two inputs) specified via the optional **func** argument.

If **func** is supplied, it should be a function of two arguments. Elements of the input iterable may be any type that can be accepted as arguments to func. You can use predefined python standard operators as functions
.

**The first value in the iterator returned by python accumulate()
is always the first value in the input sequence.**

Usually, **the number of elements output matches the input iterable**. However, if the keyword argument **initial** is provided, the accumulation leads off with the initial value so that the **output has one more element than the input iterable**.

```
def accumulate(inputs, func):
itr = iter(inputs)
prev = next(itr)
for cur in itr:
yield prev
prev = func(prev, cur)
```

#### Multiple list items

The function argument is given as operator.mul .

```
operator.mul(a, b)
operator.__mul__(a, b)
Return a * b, for a and b numbers.
```

It will return an iterator that yields all intermediate values. We can convert to list by using a list() constructor.

```
from itertools import accumulate
import operator
num = accumulate([1,2,3,4,5], operator.mul)
print (list(num))
# output
# [1, 2, 6, 24, 120]
```

**accumulate pictorial representation**:

**The first value in the iterator returned by python accumulate() is always the first value in the input sequence.**

#### default func parameter

It will return an iterator that yields all intermediate values. We can convert to a list by using **list()** constructor.

```
import itertools
num = itertools.accumulate([1,2,3,4,5])
print(num)
# output
# <itertools.accumulate object at 0x7f218a1e6bc0>
# convert iterator to list object
print(list(num))
# output
# [1, 3, 6, 10, 15]
# using reduce() for same function
from functools import reduce
import operator
r = reduce(operator.add, [1,2,3,4,5])
print(r)
# output:
# 15
```

#### own defined function

```
import itertools
def sum_numbers( *args):
return sum(args)
sum_numbers(1, 2, 3, 4)
# output:
# 10
list(itertools.accumulate([1,2,3,4,5], sum_numbers))
# output:
# [1, 3, 6, 10, 15]
```

### accumulate initial value

```
from itertools import accumulate
import operator
# it will contain more than one element in the ouptut iterable.
num = accumulate([1,2,3,4,5], operator.add, initial=10)
print(list(num))
# output:
# [10, 11, 13, 16, 20, 25]
```

**If the iterable is empty and the initial parameter is mentioned, it will return the initial value.**

```
from itertools import accumulate
import operator
num = accumulate([], operator.add, initial=10)
print(list(num))
# output:
# [10]
```

**If iterable contains one element and the initial parameter is not mentioned, it will return that element.**

```
from itertools import accumulate
num = accumulate([5], lambda x,y: x+y)
print(list(num))
# output:
# [5]
```