문제

Take a look at this:

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

Evidently, the compiler has pre-evaluated (2+3)*4, which makes sense.

Now, if I simply change the order of the operands of *:

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

The expression is no longer fully pre-evaluated! What is the reason for this? I am using CPython 2.7.3.

도움이 되었습니까?

해결책

In the first case the unoptimized code is LOAD 2 LOAD 3 ADD LOAD 4 MULTIPLY and in the second case it's LOAD 4 LOAD 2 LOAD 3 ADD MULTIPLY. The pattern matcher in fold_binops_on_constants() must handle the first ADD ok (replacing LOAD LOAD ADD with LOAD) and then follows on to do the same thing to MULTIPLY. In the second case by the time the ADD (now the second argument to MULTIPLY instead of the first) is turned into a constant the scanner is too far ahead to see L L M (when the "cursor" was on LOAD 4 it didn't look like a L L M yet).

다른 팁

Looks like this issue was patched in Python 3.3, as can be seen here.

>>> 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 
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top