是否在Python中缓存了常量计算?

aia*_*iai 14 python

假设我在Python中有一个使用常量计算浮点值的函数,如1/3.

def div_by_3(x):
    return x * (1/3)
Run Code Online (Sandbox Code Playgroud)

如果我重复调用该函数,是否会自动缓存1/3的值以提高效率?或者我是否必须手动执行以下操作?

def div_by_3(x, _ONE_THIRD=1/3):
    return x * _ONE_THIRD
Run Code Online (Sandbox Code Playgroud)

tza*_*man 13

找出适合自己的!该DIS模块非常适合检查这类东西:

>>> from dis import dis
>>> def div_by_3(x):
...     return x * (1/3.)
... 
>>> dis(div_by_3)
  2           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               1 (1)
              6 LOAD_CONST               2 (3.0)
              9 BINARY_DIVIDE       
             10 BINARY_MULTIPLY     
             11 RETURN_VALUE        
Run Code Online (Sandbox Code Playgroud)

如您所见,1/3计算每次都会发生.(注:我改变了33.强制浮师,否则它会仅仅是0.您也可以使未来的划分,这实际上改变了行为,请参见下面编辑区).

而你的第二种方法:

>>> def db3(x, _ONE_THIRD=1/3.):
...   return x * _ONE_THIRD
... 
>>> dis(db3)
  2           0 LOAD_FAST                0 (x)
              3 LOAD_FAST                1 (_ONE_THIRD)
              6 BINARY_MULTIPLY     
              7 RETURN_VALUE        
Run Code Online (Sandbox Code Playgroud)

通过检查函数对象可以找到关于第二个的更多信息:

>>> inspect.getargspec(db3)
ArgSpec(args=['x', '_ONE_THIRD'], varargs=None, keywords=None, defaults=(0.3333333333333333,))
Run Code Online (Sandbox Code Playgroud)

您可以看到默认值缓存在那里.

编辑:事实证明这有点有趣 - 在Python 3中它们会被缓存(当你启用时也在Python 2.7中from __future__ import division):

>>> dis.dis(div_by_3)
  2           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               3 (0.3333333333333333)
              6 BINARY_MULTIPLY
              7 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)

切换到//Python 3或2.7-with-division-division中的整数除法()不会改变这一点,它只是将常量改为a 0而不是0.333..另外,在2.7中直接使用整数除法而不进行未来除法将缓存0为好.

今天学到了新东西!

  • 请注意,对于Python 3,窥孔优化器*会预先计算"1/3"常量.(特别是CPython.) (4认同)