26

看看这个:

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

4

2 回答 2

9

在第一种情况下,未优化的代码是LOAD 2 LOAD 3 ADD LOAD 4 MULTIPLY,在第二种情况下,它是LOAD 4 LOAD 2 LOAD 3 ADD MULTIPLY. 中的模式匹配器fold_binops_on_constants()必须处理第一个ADDok (替换LOAD LOAD ADDLOAD),然后继续对MULTIPLY. 在第二种情况下,当ADD(现在是第二个参数MULTIPLY而不是第一个参数)变成一个常数时,扫描仪太远了,无法看到L L M(当“光标”在LOAD 4它上面时,它看起来L L M还不像)。

于 2013-07-23T01:32:04.903 回答
5

看起来这个问题在 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 
于 2013-07-25T14:56:10.620 回答