列表推导和for循环之间的性能差异

时间:2014-12-18 18:51:12

标签: python optimization list-comprehension

我有一个脚本可以找到所有数字的总和,这些数字可以写成数字的五次幂之和。 (更详细地描述了这个问题on the Project Euler web site。)

我写过两种方式,但我不了解性能差异。

第一种方法使用嵌套列表推导:

exp = 5

def min_combo(n):
    return ''.join(sorted(list(str(n))))

def fifth_power(n, exp):
    return sum([int(x) ** exp for x in list(n)])

print sum( [fifth_power(j,exp) for j in set([min_combo(i) for i in range(101,1000000) ]) if int(j) > 10 and j == min_combo(fifth_power(j,exp)) ] )

和这样的个人资料:

$ python -m cProfile euler30.py
443839   
         3039223 function calls in 2.040 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
  1007801    1.086    0.000    1.721    0.000 euler30.py:10(min_combo)
     7908    0.024    0.000    0.026    0.000 euler30.py:14(fifth_power)
        1    0.279    0.279    2.040    2.040 euler30.py:6(<module>)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
  1007801    0.175    0.000    0.175    0.000 {method 'join' of 'str' objects}
        1    0.013    0.013    0.013    0.013 {range}
  1007801    0.461    0.000    0.461    0.000 {sorted}
     7909    0.002    0.000    0.002    0.000 {sum}

第二种方式是更常见的for循环:

exp = 5
ans= 0

def min_combo(n):
    return ''.join(sorted(list(str(n))))


def fifth_power(n, exp):
    return sum([int(x) ** exp for x in list(n)])


for j in  set([ ''.join(sorted(list(str(i)))) for i in range(100, 1000000) ]):
    if int(j) > 10:

        if j ==  min_combo(fifth_power(j,exp)):
            ans += fifth_power(j,exp)

print 'answer', ans

以下是分析信息:

$ python -m cProfile euler30.py 
answer 443839
         2039325 function calls in 1.709 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     7908    0.024    0.000    0.026    0.000 euler30.py:13(fifth_power)
        1    1.081    1.081    1.709    1.709 euler30.py:6(<module>)
     7902    0.009    0.000    0.015    0.000 euler30.py:9(min_combo)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
  1007802    0.147    0.000    0.147    0.000 {method 'join' of 'str' objects}
        1    0.013    0.013    0.013    0.013 {range}
  1007802    0.433    0.000    0.433    0.000 {sorted}
     7908    0.002    0.000    0.002    0.000 {sum}

为什么列表推导实现调用min_combo()比for循环实现多1,000,000次?

1 个答案:

答案 0 :(得分:2)

因为在第二个问题上,您再次在min_combo电话中实施了set的内容......

做同样的事情,你会得到相同的结果。

顺便说一句,改变那些以避免创建大名单:

sum([something for foo in bar]) - &gt; sum(something for foo in bar)

set([something for foo in bar]) - &gt; set(something for foo in bar)

(没有[...]它们成为生成器表达式)。