免责声明:我是编程新手,但不熟悉Python。这可能是一个非常基本的问题。
我有以下代码块:
for x in range(0, 100):
y = 1 + 1;
第二行的1 + 1
计算是否执行了100次?
我有两个怀疑为什么它可能不会:
1)编译器将1 + 1
视为常量值,从而将此行编译为y = 2;
。
2)编译器发现y
仅被设置并且从未被引用,因此它省略了这行代码。
这些中的一个/两个是正确的,还是在循环中每次迭代都实际执行?
答案 0 :(得分:12)
执行选项1; CPython编译器使用窥孔优化器中的常量简化数学表达式。
Python不会消除循环体。
你可以通过查看字节码来反省Python产生的内容;使用dis
module来查看:
>>> import dis
>>> def f():
... for x in range(100):
... y = 1 + 1
...
>>> dis.dis(f)
2 0 SETUP_LOOP 26 (to 29)
3 LOAD_GLOBAL 0 (range)
6 LOAD_CONST 1 (100)
9 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
12 GET_ITER
>> 13 FOR_ITER 12 (to 28)
16 STORE_FAST 0 (x)
3 19 LOAD_CONST 3 (2)
22 STORE_FAST 1 (y)
25 JUMP_ABSOLUTE 13
>> 28 POP_BLOCK
>> 29 LOAD_CONST 0 (None)
32 RETURN_VALUE
位置19的字节码,LOAD_CONST
加载值2
以存储在y
中。
您可以在代码对象的co_consts
属性中看到与代码对象关联的常量;对于函数,您可以在__code__
属性下找到该对象:
>>> f.__code__.co_consts
(None, 100, 1, 2)
None
是任何函数的默认返回值,100
传递给range()
调用的文字,1
原始文字,由窥视孔优化器留在原位并且2
是优化的结果。
工作在peephole.c
, in the fold_binops_on_constants()
function完成:
/* Replace LOAD_CONST c1. LOAD_CONST c2 BINOP
with LOAD_CONST binop(c1,c2)
The consts table must still be in list form so that the
new constant can be appended.
Called with codestr pointing to the first LOAD_CONST.
Abandons the transformation if the folding fails (i.e. 1+'a').
If the new constant is a sequence, only folds when the size
is below a threshold value. That keeps pyc files from
becoming large in the presence of code like: (None,)*1000.
*/
考虑到Python是一种高度动态的语言,这种优化只能应用于以后无法动态替换的文字和常量。