What kind of optimization does Python do without the -O flags?

I always thought that the Python interpreter did not make optimizations without the -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 seems that the interpreter is doing some folding modulo two string constants. If I add a variable, although 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 kind of optimizations does Python do without the -O flag? And is there a way to disable them? I would like to see what Python's non-optimized bytecode will look like. I do not plan to do this in any production environment.

+4
source share
2 answers

Yes, it does a permanent crease, here is a simpler example:

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

It is not possible to block this (with the exception of changing sources) AFAIK.

Edit : for the whole stream of optimization, see peephole.c - this is probably the most convenient place for “changing sources”, for example, changing line 320 from

 if (codelen > 32700) 

to

 if (codelen > 0) 

to ensure that all optimizers are unconditionally disabled.

+9
source

Here you can navigate through the continuous 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 

Beware of additional constants:

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

All Articles