使用reduce和lambda表达式计算平方根和
我最近在学习高阶函数,想写一个函数,它可以对一系列数字进行操作。具体来说,我想让它返回从0到100之间每隔一个的平方根的总和。
def sum(lower, upper, step = 1, func = lambda *x: x):
return reduce(func, range(lower, upper + 1, step))
sum(0, 100, 2, math.sqrt)
TypeError: sqrt() takes exactly one argument (2 given)
如果有任何建议,我会很感激!
2 个回答
1
假设我们使用的是Python 3。我们先来写一个普通的代码:
result = 0
for i in range(0, 100, 2):
result += math.sqrt(i)
print(result)
接下来,我们从这里开始,朝着你想要的方向走。首先,我们把 for
循环换成 map
和 sum
。
result = sum(map(math.sqrt, range(0, 100, 2)))
print(result)
现在,我们把这个放进一个函数里。
def sum_of_the_square_roots_from_0_to_100_with_step_2():
return sum(map(math.sqrt, range(0, 100, 2)))
print(sum_of_the_square_roots_from_0_to_100_with_step_2())
接着,我们给这个函数添加一些参数。
def sum_of_func_from_0_to_100_with_step_2(func):
return sum(map(func, range(0, 100, 2)))
print(sum_of_func_from_0_to_100_with_step_2)
然后,我们也给范围添加参数。
def sum_of_func_over_range(func, *range_args):
return sum(map(func, range(*range_args)))
print(sum_of_func_over_range(math.sqrt, 0, 100, 2))
就这样!你可以传入任何一个函数(只要这个函数能接受至少一个参数)和一个范围的说明。
1
你似乎在假设 reduce
会在对每个元素应用 sort
后自动把列表中的元素加起来。也就是说,你可能认为 reduce
是这样工作的:
def reduce(func, lst, start):
return sum(map(func, lst), start)
按照现在的写法,你需要给 sum
传递一个函数,这个函数不仅要对列表中的单个值应用 math.sqrt
,还要把这个结果加到当前的总和上。
sum(0, 100, 2, lambda x, y: x + math.sqrt(y))
最简单的方法是使用我上面伪代码的主体:
def sum_of_sqroots(lower, upper, step=1, func=lambda x: x):
return sum(map(func, range(lower, upper+1, step))
在功能性编程语言之外,reduce
很少被需要(在 Python 3 中,它被“降级”从内置命名空间移到了 functools
模块),因为通常写一个明确的循环来维护一个累加器会更清晰。