这个计算是用Python执行的吗?

时间:2015-01-28 18:52:27

标签: python python-internals

  

免责声明:我是编程新手,但不熟悉Python。这可能是一个非常基本的问题。

我有以下代码块:

for x in range(0, 100):
    y = 1 + 1;

第二行的1 + 1计算是否执行了100次?

我有两个怀疑为什么它可能不会:

1)编译器将1 + 1视为常量值,从而将此行编译为y = 2;

2)编译器发现y仅被设置并且从未被引用,因此它省略了这行代码。

这些中的一个/两个是正确的,还是在循环中每次迭代都实际执行?

1 个答案:

答案 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是一种高度动态的语言,这种优化只能应用于以后无法动态替换的文字和常量。