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

Python 什么时候使用reduce()而不是sum()?,python,functional-programming,profiling,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) #-->

我最近开始学习函数式编程,在尝试计算某个班级的平均测验时,我想到了这个例子

我举的例子是:

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倍

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

reduce()
在您需要对数据列表执行任意操作时是有意义的,而不是在您已经拥有一个经过高度优化的库函数时,它不仅在小列表上优于
reduce()
,而且在大列表上大大优于它

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


Python是“函数式”的,因为它有一流的函数,但它主要不是一种函数式语言。它提供了大量用于循环的迭代器,并具有各种语言特性,使显式循环易于编写,但并不关注递归定义的列表操作(虽然它确实在一定程度上允许它们——比如说,缺乏TCO阻止我直接用Python解释Erlang或Guile代码,但确实给了我做类似事情的灵活性)。

代替sum?永远不会

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

例如,
产品
可以定义为:

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

<> > <代码>和>代码>在C.

< P> <代码>缩写和<代码>和> /代码>做非常不同的事情。考虑一个问题,比如“我有一个嵌套的字典……/P>”。
d = {'foo': {'bar': {'baz': 'qux'}}}
我想得到与键列表相关的值:
['foo',bar',baz']
”。这可能需要一个
reduce
(如果你是一个函数式编程类型的人):


注意,不能用
sum
来实现这一点。正好,求和是一个简单的例子,可以说明reduce在做什么(因为你可以用括号写出它,而且大多数程序员都熟悉括号如何组合数学运算).

抛开性能问题不谈,我必须说:使用
sum()
没有任何错误,从风格上来说,你应该选择
sum()
而不是
reduce()
reduce()
更通用,因此可以用来编写除求和之外的其他缩减。
sum()
是一种非常常见的简化方法,它值得有自己的名称和定义

例如,如果你看函数式编程语言,你会发现它们有大量用于处理序列的通用实用函数库,比如Haskell或Scheme。这些库中的许多函数可以用其他函数编写;例如,Haskell中的
map
函数可以用
foldr
(类似于
reduce()
)的术语:

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


reduce()
sum()
处于相同的关系。
reduce()
是一个构建块,当您没有像
sum()这样的函数时,可以使用它
已经存在。

如何使用
运算符。添加
而不是自定义函数?还有两点:1.
sum
可能看起来更可读,具体取决于代码的功能(在您的情况下,它会);2.@repzero函数详细信息是什么意思?@fjarri使用operator.add添加了case,sum的速度更快。我同意sum在大多数情况下可读性更好,但我想知道高阶函数什么时候可能会产生性能优势或其他类型的优势。如果您添加的类型添加速度较慢,并且希望避免一个addi,该怎么办选项?有一个重要的区别:
sum
始终使用起始值(“从左到右对起始值和iterable的项求和,并返回总数”)。
reduce(operator.add,…)
仅在提供初始值设定项时才使用它(“如果存在可选初始值设定项,则将其放在计算中iterable的项之前”)。
>>> reduce(lambda subdict, k: subdict[k], ['foo', 'bar', 'baz'], d)
'qux'
map :: (a -> b) -> [a] -> [b]
map f = foldr go []
  where f a bs = f a : bs