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

Dor*_*Ron 9 python profiling functional-programming

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

我想出的例子是:

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
Run Code Online (Sandbox Code Playgroud)

看起来在上面的例子中,使用更高阶函数几乎慢了4倍.

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

zxq*_*xq9 7

reduce()当你需要对数据列表进行任意操作时,这是有道理的,而不是当你已经拥有一个高度优化的库函数时,它不仅reduce()在小列表上胜过,而且在大型列表上大大优于它.

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

Python具有"功能性",因为它具有一流的功能,但它主要不是一种功能语言.它为循环中使用提供了丰富的迭代器供应,并具有各种语言功能,使得显式循环易于编写,但并不专注于递归定义的列表操作(尽管它确实允许它们在有限的程度上 - 缺乏TCO例如,我可以直接在Python中解释我的Erlang或Guile代码,但确实可以让我灵活地执行类似于接口类似接口的基准竞争方法.


mgi*_*son 5

reducesum做非常不同的事情。考虑这样一个问题:“我有一本嵌套字典......

d = {'foo': {'bar': {'baz': 'qux'}}}
Run Code Online (Sandbox Code Playgroud)

我想获取与键列表关联的值: ['foo', 'bar', 'baz']“。这可能需要reduce(如果您是函数式编程类型的人):

>>> reduce(lambda subdict, k: subdict[k], ['foo', 'bar', 'baz'], d)
'qux'
Run Code Online (Sandbox Code Playgroud)

请注意,您不能使用 来执行此操作sum。碰巧求和是一个简单的例子来展示reduce 发生的情况(因为你可以用括号将其写出来,并且大多数程序员都熟悉括号如何对数学运算进行分组)。

  • 实际上,它是 `reduce(dict.__getitem__, ["foo", "bar", "baz"], d)`。然后,如果密钥没有丢失,您将恢复“KeyError”行为,而不是变成可能的“TypeError:NoneType is not subscriptable”:)。 (2认同)

Lui*_*las 5

设置性能问题不谈,我不得不这样说:没有什么错都使用sum(),而且在风格上你应该选择sum()reduce()reduce()更通用,因此可用于编写其他归约,而不仅仅是求和。 sum()是一种很常见的归约,值得拥有自己的名称和定义。

如果您查看函数式编程语言,您会发现例如它们具有用于处理序列的大型通用实用程序函数库,例如 HaskellData.List或 Scheme 的SRFI-1。一个很大的可以写在其他的方面这些库中的函数; 例如,mapHaskell 中的函数可以写成foldr(类似于reduce()):

map :: (a -> b) -> [a] -> [b]
map f = foldr go []
  where f a bs = f a : bs
Run Code Online (Sandbox Code Playgroud)

但是,没有人认为,foldr从而使map不必要的或东西,以避免。相反,更通用的操作就像foldr或被reduce()视为构建更专业的功能的构建块,使程序更易于编写和理解。

reduce()并且sum()处于相同的关系中。 reduce()是一个构建块,当您没有类似的功能时,您可以使用它sum()