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倍.
所以我的问题是,何时是使用更高阶函数的好时机,因为上面的例子显然不是?
reduce()当你需要对数据列表进行任意操作时,这是有道理的,而不是当你已经拥有一个高度优化的库函数时,它不仅reduce()在小列表上胜过,而且在大型列表上大大优于它.
reduce() 为您提供了创建任意折叠的灵活性,但这种灵活性是以一些性能开销为代价的,特别是在大多数基本功能结构被认为略微超出主流的语言中.
Python具有"功能性",因为它具有一流的功能,但它主要不是一种功能语言.它为循环中使用提供了丰富的迭代器供应,并具有各种语言功能,使得显式循环易于编写,但并不专注于递归定义的列表操作(尽管它确实允许它们在有限的程度上 - 缺乏TCO例如,我可以直接在Python中解释我的Erlang或Guile代码,但确实可以让我灵活地执行类似于接口类似接口的基准竞争方法.
reduce并sum做非常不同的事情。考虑这样一个问题:“我有一本嵌套字典......
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 发生的情况(因为你可以用括号将其写出来,并且大多数程序员都熟悉括号如何对数学运算进行分组)。
设置性能问题不谈,我不得不这样说:没有什么错都使用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()。
| 归档时间: |
|
| 查看次数: |
7931 次 |
| 最近记录: |