Python是否优化了仅用作返回值的变量?

时间:2017-04-13 11:20:15

标签: python interpreter python-internals

以下两个代码段之间是否存在任何最终差异?第一个为函数中的变量赋值,然后返回该变量。第二个函数只是直接返回值。

Python会将它们变成等效的字节码吗?其中一个更快吗?

案例1

def func():
    a = 42
    return a

案例2

def func():
    return 42

2 个答案:

答案 0 :(得分:135)

不,它没有

CPython字节代码的编译仅通过一个小peephole optimizer传递,该test_peepholer.py仅用于进行基本优化(有关这些优化的更多信息,请参阅测试套件中的STORE_FAST)。

要了解实际发生的情况,请使用dis *查看生成的说明。对于第一个函数,包含赋值:

from dis import dis
dis(func)
  2           0 LOAD_CONST               1 (42)
              2 STORE_FAST               0 (a)

  3           4 LOAD_FAST                0 (a)
              6 RETURN_VALUE

虽然,对于第二个功能:

dis(func2)
  2           0 LOAD_CONST               1 (42)
              2 RETURN_VALUE

第一个使用了两个(快速)指令:LOAD_FASTdis。这些可以快速存储并获取当前执行帧的fastlocals数组中的值。然后,在两种情况下,执行RETURN_VALUE。因此,由于执行所需的命令较少,因此第二个略微更快。

通常,请注意CPython编译器在其执行的优化中是保守的。它不是并不像其他编译器一样聪明<(通常,它还有更多的信息可供使用)。除了明显正确之外,主要的设计目标是:a)保持简单和b)尽可能快地编译这些目标,这样你甚至不会注意到编译阶段存在。

最后,你不应该像这样的小问题给自己带来麻烦。速度的好处是微小的,不变的,并且与解释Python这一事实引入的开销相比是相形见绌的。

* https://github.com/mgonto/restangular是一个用于解组代码的Python模块,您可以使用它来查看VM将执行的Python字节码。

注意:正如@Jorn Vernee的评论中所述,这是特定于Python的CPython实现。如果他们愿意,其他实现可能会进行更积极的优化,CPython没有。

答案 1 :(得分:3)

两者基本相同,只是在第一种情况下,对象var declared = true; try{ theVariable; } catch(e) { if(e.name == "ReferenceError") { declared = false; } ) 只是分配给名为42的变量,换句话说,名称(即a)是指值(即a)。它从不在技术上做任何分配,因为它从不复制任何数据。

42时,在第一种情况下返回此命名绑定return,而在第二种情况下返回对象a

如需更多阅读,请参阅this great article by Ned Batchelder