是时候在 Python 中分配变量了

dkv*_*dkv 1 python variables variable-assignment assign

假设我在一个非常紧密的循环中有以下内容:

a = func(x)
b = func2(a)
Run Code Online (Sandbox Code Playgroud)

该变量a未在其他任何地方使用。

Python 会自动编译对 的赋值a,还是每次都花时间进行变量赋值?换句话说,这段代码是相同的,还是由于没有赋值而稍微快一点a

b = func2(func(x))
Run Code Online (Sandbox Code Playgroud)

Python2.7 和 Python3 的行为是否相同?

Mat*_*ory 5

因此,使用非常有趣的dis模块,我们可以查看从您提供的 python 代码生成的实际字节码。为了简单起见,我用内置函数(和)替换了func和。func2intfloat

所以我们的源码看起来是这样的:

def assign():
    a = int()
    b = float(a)
Run Code Online (Sandbox Code Playgroud)

与简化版对比:

def simple():
    b = float(int())
Run Code Online (Sandbox Code Playgroud)

然后从 cpython 2.7 解释器开始,我们可以看到从assign函数生成的字节码:

dis.dis(assign)
  2           0 LOAD_GLOBAL              0 (int)
              3 CALL_FUNCTION            0
              6 STORE_FAST               0 (a)

  3           9 LOAD_GLOBAL              1 (float)
             12 LOAD_FAST                0 (a)
             15 CALL_FUNCTION            1
             18 STORE_FAST               1 (b)
             21 LOAD_CONST               0 (None)
             24 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)

如您所见,没有去除不必要的中间变量的窥视孔优化,与简化的`simple 方法的字节码相比,这会导致额外的 2 条指令 ( STORE_FAST a, LOAD_FAST a):

dis.dis(simple)
  2           0 LOAD_GLOBAL              0 (float)
              3 LOAD_GLOBAL              1 (int)
              6 CALL_FUNCTION            0
              9 CALL_FUNCTION            1
             12 STORE_FAST               0 (b)
             15 LOAD_CONST               0 (None)
             18 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)

这对于 Python 3.5 的 CPython 解释器和 Python 2.7 的 pypy 解释器是相同的。