Python是否优化掉了一个变量';s仅用作返回值?
以下两段代码之间有什么根本的区别吗?首先为函数中的变量赋值,然后返回该变量。第二个函数直接返回值 Python是否将它们转换为等效字节码?其中一个更快吗 案例1:Python是否优化掉了一个变量';s仅用作返回值?,python,interpreter,python-internals,Python,Interpreter,Python Internals,以下两段代码之间有什么根本的区别吗?首先为函数中的变量赋值,然后返回该变量。第二个函数直接返回值 Python是否将它们转换为等效字节码?其中一个更快吗 案例1: def func(): a = 42 return a def func(): return 42 案例2: def func(): a = 42 return a def func(): return 42 不,没有 对CPython字节码的编译只通过一个小的程序进行,该程序设
def func():
a = 42
return a
def func():
return 42
案例2:
def func():
a = 42
return a
def func():
return 42
不,没有
对CPython字节码的编译只通过一个小的程序进行,该程序设计为只进行基本优化(有关这些优化的更多信息,请参阅测试套件中的)
要查看实际发生的情况,请使用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
在第一个:和中使用了另外两个(快速)指令。它们在当前执行帧的fastlocals
数组中快速存储和获取值。然后,在这两种情况下,执行返回值
。因此,由于需要执行的命令较少,第二个命令的执行速度稍快
通常,请注意CPython编译器在执行优化时是保守的。它不是,也没有试图像其他编译器那样聪明(一般来说,它们也有更多的信息要处理)。除了明显正确之外,主要的设计目标是a)保持简单,b)在编译这些文件时尽可能快,这样您就不会注意到编译阶段的存在
最后,你不应该为这样的小问题而烦恼。速度方面的好处是微小的、恒定的和稳定的,与Python被解释这一事实所带来的开销相形见绌
*是一个分解代码的小Python模块,您可以使用它查看VM将执行的Python字节码
注意:正如@Jorn Vernee在评论中所述,这是特定于Python的CPython实现的。其他实现可能会进行更积极的优化,如果他们愿意的话,CPython不会。两者基本相同,只是在第一种情况下,对象
42
只是被分配到名为a
的变量,或者换句话说,名称(即a
)指的是值(即42
)。它在技术上不做任何分配,因为它从不复制任何数据
当return
ing时,在第一种情况下返回此命名绑定a
,而在第二种情况下返回对象42
要了解更多信息,请参阅如果您在两个屏幕上都使用了
dis.dis(..)
,您会发现它们之间存在差异,所以是的。但在大多数实际应用程序中,与函数中的处理延迟相比,该函数的开销并没有那么大。有两种可能性:(a)您将在一个紧密循环中多次(即至少一百万次)调用该函数。在这种情况下,您根本不应该调用Python函数,而是应该使用numpy库之类的工具对循环进行矢量化。(b) 您不会多次调用此函数。在这种情况下,这些函数之间的速度差异太小,不值得担心。不是python人员(c++),所以我不知道它是如何工作的,但第一种情况不应该优化为第二种情况吗?一个不错的C++编译器会做出这种优化。@ NaNaOLIVER确实不这样,Python将在这里做的,甚至没有试图玩它聪明。事实上,NaNaulver的完全合理和智能猜测在回答这个问题是完全错误的,在我看来,这不是一个“自我解释”,“胡说”,“愚蠢”的问题可以通过“花点时间思考”来回答,就像TigerhawkT3让我们相信的那样。这是一个有效的、有趣的问题,尽管我多年来一直是专业的Python程序员,但我不确定答案。Python的编译器充其量是“保守的”,而不是“非常保守的”。主要的设计目标是尽快。。。所以你甚至没有注意到编译阶段的存在。”这是第二阶段,在“保持简单”之后1@AndrewDalke感谢内部人士对此的评论,我调整了措辞以解决您指出的问题。