Python for循环执行

时间:2013-01-25 13:15:36

标签: python for-loop python-2.7

for a in sorted(arr):
    doSomething()

VS

sArr = sorted(arr)
for a in sArr:
    doSomething()

那两个是完全相同的,还是会比另一个消耗更多的cpu周期?

意思是,在第一个例子中,每个循环都会调用(arr)调用吗?

感谢

4 个答案:

答案 0 :(得分:5)

他们几乎一样。

The documentation说:

  

表达式列表评估一次;它应该产生一个可迭代的对象。

因此,在上述代码中,sorted()调用不会发生多次调用的风险。

第一种形式仍然更好,因为它更短更简洁,并且可以更好地进行优化(因为解释器可以在循环结束后发现排序列表完全超出范围)。

答案 1 :(得分:4)

完全不一样,但差别很小。如有疑问,请使用dis模块查找:

>>> import dis
>>> def f():
...     for a in sorted(arr):
...         doSomething()
... 
>>> def g():
...     sArr = sorted(arr)
...     for a in sArr:
...         doSomething()
... 
>>> dis.dis(f)
  2           0 SETUP_LOOP              27 (to 30)
              3 LOAD_GLOBAL              0 (sorted)
              6 LOAD_GLOBAL              1 (arr)
              9 CALL_FUNCTION            1
             12 GET_ITER            
        >>   13 FOR_ITER                13 (to 29)
             16 STORE_FAST               0 (a)

  3          19 LOAD_GLOBAL              2 (doSomething)
             22 CALL_FUNCTION            0
             25 POP_TOP             
             26 JUMP_ABSOLUTE           13
        >>   29 POP_BLOCK           
        >>   30 LOAD_CONST               0 (None)
             33 RETURN_VALUE        
>>> dis.dis(g)
  2           0 LOAD_GLOBAL              0 (sorted)
              3 LOAD_GLOBAL              1 (arr)
              6 CALL_FUNCTION            1
              9 STORE_FAST               0 (sArr)

  3          12 SETUP_LOOP              21 (to 36)
             15 LOAD_FAST                0 (sArr)
             18 GET_ITER            
        >>   19 FOR_ITER                13 (to 35)
             22 STORE_FAST               1 (a)

  4          25 LOAD_GLOBAL              2 (doSomething)
             28 CALL_FUNCTION            0
             31 POP_TOP             
             32 JUMP_ABSOLUTE           19
        >>   35 POP_BLOCK           
        >>   36 LOAD_CONST               0 (None)
             39 RETURN_VALUE        

如您所见,g()函数添加了STORE_FASTLOAD_FAST操作。您还可以使用更多的内存,因为排序的结果会被保留,直到sArr变量被清除,而在f()中,排序的结果可以在循环结束后立即清除。 / p>

CALL_FUNCTION执行sorted()功能;它只执行一次。

答案 2 :(得分:1)

sorted()返回一个随后迭代的对象。它只被调用一次。

答案 3 :(得分:0)

与其他人所说的相同。请记住,如果有疑问(虽然在这种情况下是微不足道的,显而易见的)总是在源上运行反汇编。或者,您可以通过cProfile运行它,即使反汇编不同,cProfile也会对性能有一个合理的了解

>>> def foo():
    total = 0
    arr = range(10000000,1,-1)
    for a in sorted(arr):
        total += a


>>> def bar():
    total = 0
    for a in sorted(range(10000000,1,-1)):
        total += a


>>> cProfile.run("bar()")
         5 function calls in 2.614 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    1.914    1.914    2.614    2.614 <pyshell#88>:1(bar)
        1    0.000    0.000    2.614    2.614 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        1    0.266    0.266    0.266    0.266 {range}
        1    0.434    0.434    0.434    0.434 {sorted}


>>> cProfile.run("foo()")
         5 function calls in 2.477 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    1.779    1.779    2.346    2.346 <pyshell#86>:1(foo)
        1    0.130    0.130    2.477    2.477 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        1    0.152    0.152    0.152    0.152 {range}
        1    0.415    0.415    0.415    0.415 {sorted}


>>> 

正如你在这里观察到的那样

  1. 在两种情况下仅调用一次排序
  2. 每种情况下有5个函数调用
  3. 他们的表现几乎相同。