2010-01-10 7 views
4

J'avais toujours supposé que l'interpréteur Python n'a aucune optimisation sans drapeau -O, mais ce qui suit est un peu étrange:Quelles optimisations Python fait sans les drapeaux -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   

Il semble que l'interprète fait un certain pliage sur le modulo de deux constantes de chaîne . Si j'ajoute une variable cependant, il donne un résultat unoptimized:

>>> 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   

Qu'est-ce que les optimisations ne Python sans faire le drapeau -O? Et est-il possible de les désactiver? Je voudrais voir à quoi ressemblera Python bytecode non optimisé. Je ne prévois pas de le faire dans n'importe quel environnement de production.

Répondre

9

Eh oui, il ne fait plier constante, voici un exemple plus simple:

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

Aucun moyen de bloquer ce (sauf en changeant les sources) AFAIK.

Modifier: pour tout le flux d'optimisation, voir peephole.c - c'est probablement aussi l'endroit le plus pratique pour "changer les sources", par ex. changement ligne 320 de

if (codelen > 32700) 

à

if (codelen > 0) 

pour vous assurer que toutes les optimisations sont désactivées sans conditions.

0

est ici une façon de marcher autour de pliage constante:

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

Attention pour les constantes supplémentaires, si:

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