Подтвердить что ты не робот

Почему эти две функции различны?

Взгляните на это:

>>> def f():
...     return (2+3)*4
... 
>>> dis(f)
  2           0 LOAD_CONST               5 (20)
              3 RETURN_VALUE  

Очевидно, компилятор предварительно оценил (2+3)*4, что имеет смысл.

Теперь, если я просто изменил порядок операндов *:

>>> def f():
...     return 4*(2+3)
... 
>>> dis(f)
  2           0 LOAD_CONST               1 (4)
              3 LOAD_CONST               4 (5)
              6 BINARY_MULTIPLY     
              7 RETURN_VALUE  

Выражение уже не полностью предварительно оценивается! Что является причиной этого? Я использую CPython 2.7.3.

4b9b3361

Ответ 1

В первом случае неоптимизированный код LOAD 2 LOAD 3 ADD LOAD 4 MULTIPLY, а во втором случае он LOAD 4 LOAD 2 LOAD 3 ADD MULTIPLY. Шаблон сопоставления в fold_binops_on_constants() должен обрабатывать первый ADD ok (заменяя LOAD LOAD ADD на LOAD), а затем следует сделать то же самое с MULTIPLY. Во втором случае к тому времени, когда ADD (теперь второй аргумент MULTIPLY вместо первого) превращается в константу, сканер слишком далеко впереди, чтобы увидеть L L M (когда "курсор" был включен LOAD 4 он еще не был похож на L L M).

Ответ 2

Похоже, эта проблема была исправлена ​​в Python 3.3, как можно видеть здесь.

>>> def f():
...     return (2+3)*4
... 
>>> dis(f)
  2           0 LOAD_CONST               5 (20)
              3 RETURN_VALUE  
>>> def f():
...     return 4*(2+3)
... 
>>> dis(f)
  2           0 LOAD_CONST               5 (20)
              3 RETURN_VALUE