高阶函数与循环 - 运行时间和内存效率?

8 投票
2 回答
2249 浏览
提问于 2025-04-17 11:16

使用高阶函数和Lambda表达式会让运行时间和内存效率变得更好还是更差呢?

比如说,要把一个列表里的所有数字都乘起来:

nums = [1,2,3,4,5]
prod = 1
for n in nums:
    prod*=n

prod2 = reduce(lambda x,y:x*y , nums)

高阶函数的写法除了代码行数少、采用了函数式编程的方式之外,还有什么优点吗?

补充:

我不能把这个作为答案发出去,因为我的声望不够。我试着用@DSM建议的timeit工具来分析循环和高阶函数的方法。

def test1():         
    s= """
    nums = [a for a in range(1,1001)] 
    prod = 1 
    for n in nums:
        prod*=n
    """            
    t = timeit.Timer(stmt=s)
    return t.repeat(repeat=10,number=100)    

def test2():
    s="""
    nums = [a for a in range(1,1001)]     
    prod2 = reduce(lambda x,y:x*y , nums)
    """
    t = timeit.Timer(stmt=s)
    return t.repeat(repeat=10,number=100) 

这是我的结果:

Loop:
[0.08340786340144211, 0.07211491653462579, 0.07162720686361926, 0.06593182661083438, 0.06399049758613146, 0.06605228229559557, 0.06419744588664211, 0.0671893658461038, 0.06477527090075941, 0.06418023793167627]
test1 average: 0.0644778902685
HOF:
[0.0759414223099324, 0.07616920129277016, 0.07570730355421262, 0.07604965128984942, 0.07547092059389193, 0.07544737286604364, 0.075532959799953, 0.0755039779810629, 0.07567424616704144, 0.07542563650187661]
test2 average: 0.0754917512762

平均来看,循环的方法似乎比使用高阶函数要快。

2 个回答

1

根据我的经验,循环可以非常快速地执行任务,只要它们的嵌套层数不要太深,而且涉及的数学运算也不要太复杂。对于简单的操作和单层循环,速度可能和其他方法一样快,甚至更快,只要循环的索引使用的是整数,具体速度还得看你在做什么。

另外,高阶函数可能会产生和循环程序版本一样多的循环,甚至可能会稍微慢一些。你最好还是把两者的执行时间测一下,才能确定哪个更快。

7

高阶函数的执行速度可以非常快。

举个例子,map(ord, somebigstring) 的速度要比等效的列表推导式 [ord(c) for c in somebigstring] 快得多。这种情况有三个原因:

  • map() 在开始时就为结果字符串预先分配了和 somebigstring 一样的长度。而列表推导式在增长时需要多次调用 realloc() 来调整大小。

  • map() 只需要查找一次 ord,先在全局变量中查找,然后在内置函数中找到。而列表推导式在每次循环时都要重复这个查找过程。

  • map 的内部循环运行速度接近 C 语言的速度。而列表推导式的循环体则是由一系列纯 Python 的步骤组成,每一步都需要通过 eval 循环来处理。

这里有一些时间测试来确认这个预测:

>>> from timeit import Timer
>>> print min(Timer('map(ord, s)', 's="x"*10000').repeat(7, 1000))
0.808364152908
>>> print min(Timer('[ord(c) for c in s]', 's="x"*10000').repeat(7, 1000))
1.2946639061

撰写回答