没有-O标志,Python会做什么优化?

时间:2010-01-10 20:26:28

标签: python optimization bytecode

我一直认为Python解释器在没有-O标志的情况下没有进行优化,但以下内容有点奇怪:

>>> def foo():
...     print '%s' % 'Hello world'
...
>>> from dis import dis 
>>> dis(foo)
  2           0 LOAD_CONST               3 ('Hello world')
              3 PRINT_ITEM          
              4 PRINT_NEWLINE       
              5 LOAD_CONST               0 (None)
              8 RETURN_VALUE        

好像解释器在两个字符串常量的模数上做了一些折叠。如果我添加一个变量,它会给出一个未经优化的结果:

>>> def foo():
...     s = 'Hello world!'
...     print '%s' % s
... 
>>> dis(foo)
  2           0 LOAD_CONST               1 ('Hello world!')
              3 STORE_FAST               0 (s)

  3           6 LOAD_CONST               2 ('%s')
              9 LOAD_FAST                0 (s)
             12 BINARY_MODULO       
             13 PRINT_ITEM          
             14 PRINT_NEWLINE       
             15 LOAD_CONST               0 (None)
             18 RETURN_VALUE        

没有-O标志,Python会做什么优化?有没有办法禁用它们?我想看看未经优化的Python字节码看起来如何。我不打算在任何生产类型的环境中这样做。

2 个答案:

答案 0 :(得分:9)

是的,它确实做了常数折叠,这是一个更简单的例子:

>>> def f(): return 23+100
... 
>>> dis.dis(f)
  1           0 LOAD_CONST               3 (123)
              3 RETURN_VALUE        
>>> 

无法阻止此(除非更改来源)AFAIK。

修改:对于所有优化流程,请参阅peephole.c - 这也可能是“更改来源”的最方便的地方,例如从

更改第320行
if (codelen > 32700)

if (codelen > 0)

确保无条件禁用所有优化。

答案 1 :(得分:0)

这是一种绕恒定折叠走路的方法:

>>> dis.dis(lambda: (3,)[0]+(4,)[0])
  1           0 LOAD_CONST               5 (3)
              3 LOAD_CONST               7 (4)
              6 BINARY_ADD          
              7 RETURN_VALUE        

注意额外的常数:

>>> (lambda: (3,)[0]+(4,0)[0]).func_code.co_consts
(None, 3, 0, 4, (3,), 3, (4, 0), 4)