在循环的每次重复中都调用了foo()吗?
for num in foo():
# Do something
如果效率低下,这段代码会更好吗?
l = foo()
for num in l:
# Do something
答案 0 :(得分:3)
没有。在foo()
中只调用一次。可以预期前者比后者略快。此外,list
是内置函数/类型的名称,您不应将其用作变量名。
您可以使用Python字节码反汇编程序dis.dis
来查找CPython生成的字节码:
>>> import dis
>>> dis.dis(compile('for num in foo():pass', '', 'exec'))
1 0 SETUP_LOOP 17 (to 20)
3 LOAD_NAME 0 (foo)
6 CALL_FUNCTION 0 (0 positional, 0 keyword pair)
9 GET_ITER
>> 10 FOR_ITER 6 (to 19)
13 STORE_NAME 1 (num)
16 JUMP_ABSOLUTE 10
>> 19 POP_BLOCK
>> 20 LOAD_CONST 0 (None)
23 RETURN_VALUE
在上面的字节码中,循环体从10 FOR_ITER
开始,一直持续到19 POP_BLOCK
。与:比较:
>>> dis.dis(compile('l = foo()\nfor num in list:pass', '', 'exec'))
1 0 LOAD_NAME 0 (foo)
3 CALL_FUNCTION 0 (0 positional, 0 keyword pair)
6 STORE_NAME 1 (l)
2 9 SETUP_LOOP 14 (to 26)
12 LOAD_NAME 1 (l)
15 GET_ITER
>> 16 FOR_ITER 6 (to 25)
19 STORE_NAME 2 (num)
22 JUMP_ABSOLUTE 16
>> 25 POP_BLOCK
>> 26 LOAD_CONST 0 (None)
29 RETURN_VALUE
这里循环体从位置16开始,一直持续到25.循环体的字节码是相同的;唯一的区别是用于将STORE_NAME
的返回值存储到foo()
的额外操作码list
,以及用于从LOAD_NAME
检索值的额外list
。