这个计算是在Python中执行的吗?
Is this calculation executed in Python?
Disclaimer: I'm new to programming, but new to Python. This may be a pretty basic question.
我有以下代码块:
for x in range(0, 100):
y = 1 + 1;
第二行1 + 1
的计算是否执行了100次?
我有两个怀疑为什么不能:
1) 编译器将1 + 1
视为常量值,因此将这一行编译成y = 2;
.
2) 编译器看到y
只被设置而没有被引用,所以省略了这行代码。
这些 either/both 是否正确,或者它实际上在循环中的每次迭代中都执行了吗?
选项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
是任何函数的默认 return 值,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 是一种高度动态的语言,此类优化只能应用于以后无法动态替换的文字和常量。
Disclaimer: I'm new to programming, but new to Python. This may be a pretty basic question.
我有以下代码块:
for x in range(0, 100):
y = 1 + 1;
第二行1 + 1
的计算是否执行了100次?
我有两个怀疑为什么不能:
1) 编译器将1 + 1
视为常量值,因此将这一行编译成y = 2;
.
2) 编译器看到y
只被设置而没有被引用,所以省略了这行代码。
这些 either/both 是否正确,或者它实际上在循环中的每次迭代中都执行了吗?
选项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
是任何函数的默认 return 值,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 是一种高度动态的语言,此类优化只能应用于以后无法动态替换的文字和常量。