for a in sorted(arr):
doSomething()
对比
sArr = sorted(arr)
for a in sArr:
doSomething()
这两个是否完全相同,或者一个会消耗更多的 CPU 周期然后另一个?
意思是, sorted(arr) 在第一个示例中的每个循环都会被调用吗?
谢谢
for a in sorted(arr):
doSomething()
对比
sArr = sorted(arr)
for a in sArr:
doSomething()
这两个是否完全相同,或者一个会消耗更多的 CPU 周期然后另一个?
意思是, sorted(arr) 在第一个示例中的每个循环都会被调用吗?
谢谢
它们几乎相同。
文档说:
表达式列表被评估一次;它应该产生一个可迭代的对象。
因此,sorted()
在上面的代码中,不会有多次调用的风险。
第一种形式仍然更好,因为它更短更简洁,并且可以更好地优化(因为解释器可以确定循环结束后排序列表完全超出范围)。
它们并不完全相同,但差异很小。如有疑问,请使用该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
andLOAD_FAST
操作。您还使用了更多的内存,因为已排序的结果会保留在sArr
变量被清理之前,而在f()
循环结束后可以立即清理已排序的结果。
执行函数CALL_FUNCTION
;sorted()
它只执行一次。
sorted()
返回一个随后被迭代的对象。它只被调用一次。
和其他人说的一样。请记住,当有疑问时(尽管在这种情况下微不足道且显而易见),请始终在源代码上运行反汇编。或者,您可以通过 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}
>>>
正如你会在这里观察到的