0

I'm trying to run the following code:

print(reduce(lambda x, y: x + y, [1,2,3,4,5]))

O/P -> 15

What is x and y? Which is the accumulator here? Does the accumulator always has to be the first argument (i.e. x here) What happens when no initialization is done? What is the default value picked?

Wolf
  • 9,679
  • 7
  • 62
  • 108
Prateek B
  • 11
  • 2

2 Answers2

1

An extended form of this code which would might be easier to understand

lst = [1, 2, 3, 4, 5]

x = 0  # Default value
for i in lst:
    y = i
    x = x + y
print(x)

Or, if you consider the lambda function:

lst = [1, 2, 3, 4, 5]
x = 0

def func(x,y):
    x = x + y
    return x

for i in lst:
    x = func(x, i)

print(x)

As you can see, x is the accumulator here. You won't be able to use the reduce method if you don't specify the accumulator as the first argument.

Hope that clears how your code works.

Update: As @Wolf points out, we can specify an initial value for the args for reduce method. Updated x to be 0, as that is the default value.

JRajan
  • 672
  • 4
  • 19
  • 1
    The list that OP used is `[1, 2, 3, 4, 5]`. But my assumption regarding the initial value was incorrect as pointed out by your answer. – JRajan Apr 06 '21 at 11:14
  • 1
    However, you are probably right in the idea to switch to a loop. This seems the advice given indirectly by moving the `reduce` function from built-in functions to `functools`, see https://stackoverflow.com/q/181543/2932052 for more – Wolf Apr 06 '21 at 14:29
1

I think the documentation of functools.reduce(function, iterable[, initializer]) is quite readable. The iteration is carried out, applying the operation from left to right to consecutive elements and accumulating the result in the left operand. To be sure about the aspects in question, it helps to create variations of above code.

In the following example, we get the sum of the elements; we see that there is no implicit 1 as "default" value at work:

>>> print(reduce(lambda x, y: x + y, [2,3]))
5

The reduction stops if there are no elements left in the iterable:

>>> print(reduce(lambda x, y: x + y, [1]))
1

The reduction fails if there are no elements at all:

>>> print(reduce(lambda x, y: x + y, []))
Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    print(reduce(lambda x, y: x + y, []))
TypeError: reduce() of empty sequence with no initial value

The optional initializer value is used to start the reduction (and immediately stops it if there are no elements):

>>> print(reduce(lambda x, y: x + y, [], 0))
0

So x is indeed the accumulator that is initialized with the optional initializer value before entering the iterable. And y is the next value from the iterable, if there are no elements (left), the function is ignored.

Here another example to better understand the roles of x and y:

>>> print(reduce(lambda x, y: x - y, [1,2,3], 10))
4

In single-step mode, above reduction would look like this:

x = 10   # initializer
y = 1    # from iterable
x = x-y  # x==9
y = 2    # from iterable
x = x-y  # x==7
y = 3    # from iterable
x = x-y  # x==4
4        # result
Wolf
  • 9,679
  • 7
  • 62
  • 108