Reputation: 198517
I had always assumed that the Python interpreter did no optimizations without a -O
flag, but the following is a bit strange:
>>> 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
It appears as though the interpreter is doing some folding on the modulo of two string constants. If I add a variable in though, it gives an unoptimized result:
>>> 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
What optimizations does Python do without the -O flag? And is there any way to disable them? I'd like to see how unoptimized Python bytecode will look. I don't plan on doing this in any production type environment.
Upvotes: 4
Views: 339
Reputation: 11561
Here's a way to walk around constant folding:
>>> dis.dis(lambda: (3,)[0]+(4,)[0])
1 0 LOAD_CONST 5 (3)
3 LOAD_CONST 7 (4)
6 BINARY_ADD
7 RETURN_VALUE
Watch out for the extra constants, though:
>>> (lambda: (3,)[0]+(4,0)[0]).func_code.co_consts
(None, 3, 0, 4, (3,), 3, (4, 0), 4)
Upvotes: 0
Reputation: 881477
Yep, it does do constant folding, here's a simpler example:
>>> def f(): return 23+100
...
>>> dis.dis(f)
1 0 LOAD_CONST 3 (123)
3 RETURN_VALUE
>>>
No way to block this (except by changing sources) AFAIK.
Edit: for all the optimization flow, see peephole.c -- this is also probably the handiest place to "change sources", e.g. change line 320 from
if (codelen > 32700)
to
if (codelen > 0)
to make sure all optimizations are unconditionally disabled.
Upvotes: 9