你什么时候使用reduce()而不是sum()?

时间:2015-11-18 04:53:17

标签: python functional-programming profiling

我最近开始学习函数式编程,并在尝试计算一个类的测验平均值时提出了这个例子。

我提出的例子是:

scores = [90, 91, 92, 94, 95, 96, 97, 99, 100]

def add(num1, num2):
    '''returns the sum of the parameters'''
    return num1 + num2

import operator 

timeit reduce(add, scores) / len(scores)  #--> 1000000 loops, best of 3: 799 ns per loop

timeit sum(scores) / len(scores)  #--> 1000000 loops, best of 3: 207 ns per loop

timeit reduce(operator.add, scores) / len(scores) #--> 1000000 loops, best of 3: 485 ns per loop

在上面的例子中,似乎使用更高阶函数几乎要慢4倍。

所以我的问题是,何时是使用更高阶函数的好时机,因为上面的例子显然不是?

4 个答案:

答案 0 :(得分:5)

当您需要对数据列表进行任意操作时,

reduce()才有意义,而不是当您已经拥有一个不仅优于reduce()的高度优化的库函数时小名单,但大幅在较大的名单上胜过它。

reduce()为您提供了创建任意折叠的灵活性,但这种灵活性是以一些性能开销为代价的,特别是在大多数基本功能结构被认为略微偏离主流的语言中。

Python具有“功能性”,因为它具有一流的功能,但它主要不是一种功能语言。它为循环中使用提供了丰富的迭代器供应,并具有各种语言功能,使得显式循环易于编写,但并不专注于递归定义的列表操作(尽管它确实允许它们在有限的程度上 - 缺乏TCO例如,我可以直接在Python中解释我的Erlang或Guile代码,但确实可以让我灵活地执行benchmark competing approaches that adhere to similar interfaces}之类的操作。

答案 1 :(得分:2)

除了设置性能问题之外,我不得不这样说:使用sum()时没有任何问题,而且风格上你选择sum()结束reduce()reduce()更通用,因此可用于编写其他减少而不仅仅是求和。 sum()是一种常见的缩减,它具有自己的名称和定义。

如果你看一下函数式编程语言,你会发现它们有很多用于处理序列的通用实用函数库,比如Haskell' Data.List或Scheme' {{3} }。这些库中的函数的 lot 可以用其他函数编写;例如,Haskell中的map函数可以用foldr(类似于reduce())来编写:

map :: (a -> b) -> [a] -> [b]
map f = foldr go []
  where f a bs = f a : bs

但没有人认为foldr因此map不必要或需要避免。相反,像foldrreduce()这样的更一般的操作被视为构建块,以构建更专业的函数,使程序更易于编写和理解。

reduce()sum()属于同一种关系。 reduce()是您在没有像sum()这样的功能时可以使用的构建基块。

答案 2 :(得分:1)

代替总和?从不。

但是,通过自定义方法进行聚合时,减少调用将是一种方法。

例如product可以定义为:

product = lambda iterable: reduce(operator.mul, iterable)

同样sum在C。

中实施

答案 3 :(得分:0)

reducesum做了很多不同的事情。考虑像&#34这样的问题;我有一个嵌套字典......

d = {'foo': {'bar': {'baz': 'qux'}}}

我希望获得与密钥列表相关联的值:['foo', 'bar', 'baz']"。这个可以调用reduce(如果你是一个函数式编程人员):

>>> reduce(lambda subdict, k: subdict[k], ['foo', 'bar', 'baz'], d)
'qux'

注意,您无法使用sum执行此操作。只是汇总是一个简单的例子,用于显示减少发生的事情(因为你可以用括号写出来,大多数程序员都熟悉括号组的数学运算)。