Какие оптимизации делает Python без флагов -O? - PullRequest
4 голосов
/ 10 января 2010

Я всегда предполагал, что интерпретатор 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        

Какие оптимизации выполняет Python без флага -O?И есть ли способ их отключить?Я хотел бы посмотреть, как будет выглядеть неоптимизированный байт-код Python.Я не планирую делать это в любой среде производственного типа.

Ответы [ 2 ]

9 голосов
/ 10 января 2010

Да, это делает постоянное сворачивание, вот более простой пример:

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

, чтобы убедиться, что все оптимизации безоговорочно отключены.

0 голосов
/ 06 апреля 2014

Вот способ обойти постоянное складывание:

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