for a in sorted(arr):
doSomething()
VS
sArr = sorted(arr)
for a in sArr:
doSomething()
那两个是完全相同的,还是会比另一个消耗更多的cpu周期?
意思是,在第一个例子中,每个循环都会调用(arr)调用吗?
感谢
答案 0 :(得分:5)
他们几乎一样。
表达式列表评估一次;它应该产生一个可迭代的对象。
因此,在上述代码中,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_FAST
和LOAD_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}
>>>
正如你在这里观察到的那样