我一直认为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字节码看起来如何。我不打算在任何生产类型的环境中这样做。
答案 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)