"TypeError: <lambda>() takes 1 positional argument but 2 were given" using reduce()

Question:

I want to return sum of square of numbers passed in list.

from functools import reduce

def square_sum(numbers):
    return reduce(lambda x: x ** 2, numbers)

print(square_sum([1, 2, 2]))

However i am getting the error: TypeError: <lambda>() takes 1 positional argument but 2 were given.
I couldn’t understand reason behind it.

Asked By: mind overflow

||

Answers:

Here’s how you might define sum if it didn’t exist:

from functools import reduce

def sum(it):
    return reduce(lambda acc, val: acc + val, it)

Or:

from functools import reduce
import operator

def sum(it):
    return reduce(operator.add, it)

functools.reduce reduces the values produced by an iterator to a single value by repeatedly combining consecutive values using the function you provide. So the function needs to be able to combine two values and therefore must take two arguments.

So you could define sum_of_squares using reduce, like this, although there are a lot of corner cases to cope with:

from functools import reduce

def sum_of_squares(it):
    it = iter(it)
    try:
        first = next(it)
    except StopIteration:
        return 0
    return reduce(lambda acc, val: acc + val * val,
                  it,
                  first * first)

Personally, I think the following is clearer:

def sum_of_squares(it):
    return sum(map(lambda x: x ** 2, it))
Answered By: rici

The function parameter to reduce() should take two arguments: an old one and a new one. To sum, you’d just need to add them together:

lambda r, x: x**2 + r

However, that doesn’t get the right answer if the first element is >1. You might be thinking reduce() is like sum(map()):

def square_sum(numbers):
    return sum(map(lambda x: x**2, numbers))

But it’s more readable to replace the map with a generator expression:

def square_sum(numbers):
    return sum(x**2 for x in numbers)

print(square_sum([1, 2, 2]))  # -> 9
Answered By: wjandrea
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.