在python中,返回前的分配是否有成本?
给定两个类似的python函数:在python中,返回前的分配是否有成本?,python,optimization,Python,Optimization,给定两个类似的python函数: def get_text(filename): with open(filename, 'rb') as f: text = pickle.load(f) return text 及 在get_text和get_text 2之间是否有性能差异?或者python解释器在返回之前还必须在幕后完成一项任务吗 这个问题主要是关于在返回之前对局部变量的赋值——取消勾选文件部分只是我手头上一个方便的例子。感谢@jornsharpe提到我可以d
def get_text(filename):
with open(filename, 'rb') as f:
text = pickle.load(f)
return text
及
在get_text
和get_text 2
之间是否有性能差异?或者python解释器在返回之前还必须在幕后完成一项任务吗
这个问题主要是关于在返回之前对局部变量的赋值——取消勾选文件部分只是我手头上一个方便的例子。感谢@jornsharpe提到我可以
dis
,我认为这提供了答案:
这是通过python 3.7.1完成的
>>> def get_text(filename):
... with open(filename, 'rb') as f:
... text = pickle.load(f)
... return text
...
>>> def get_text2(filename):
... with open(filename, 'rb') as f:
... return pickle.load(f)
...
>>> import dis
>>> dis.dis(get_text)
2 0 LOAD_GLOBAL 0 (open)
2 LOAD_FAST 0 (filename)
4 LOAD_CONST 1 ('rb')
6 CALL_FUNCTION 2
8 SETUP_WITH 16 (to 26)
10 STORE_FAST 1 (f)
3 12 LOAD_GLOBAL 1 (pickle)
14 LOAD_METHOD 2 (load)
16 LOAD_FAST 1 (f)
18 CALL_METHOD 1
20 STORE_FAST 2 (text)
22 POP_BLOCK
24 LOAD_CONST 0 (None)
>> 26 WITH_CLEANUP_START
28 WITH_CLEANUP_FINISH
30 END_FINALLY
4 32 LOAD_FAST 2 (text)
34 RETURN_VALUE
>>> dis.dis(get_text2)
2 0 LOAD_GLOBAL 0 (open)
2 LOAD_FAST 0 (filename)
4 LOAD_CONST 1 ('rb')
6 CALL_FUNCTION 2
8 SETUP_WITH 12 (to 22)
10 STORE_FAST 1 (f)
3 12 LOAD_GLOBAL 1 (pickle)
14 LOAD_METHOD 2 (load)
16 LOAD_FAST 1 (f)
18 CALL_METHOD 1
20 RETURN_VALUE
>> 22 WITH_CLEANUP_START
24 WITH_CLEANUP_FINISH
26 END_FINALLY
28 LOAD_CONST 0 (None)
30 RETURN_VALUE
立即返回的get_text2
版本避免了STORE_FAST
、POP_BLOCK
和LOAD_FAST
指令,但我同意成本可能可以忽略不计
我认为在许多情况下,立即返回也会导致更短更干净的代码。可能是的。表示需要额外的指令(
store\u fast
,load\u fast
)。但与实际读取文件相比,我怀疑这是一个瓶颈。我不确定解释器是否被允许对此进行优化。理论上,您可以检查调用堆栈并检查text
是否作为本地变量存在于get\u text
中。为什么要问我们?你面前有最高的权威。使用timeit
模块运行实证测试。通常我们不担心分配时间。那只是一些指针操作。现在,将创建或复制新对象。我会将返回内容放在with上下文之外,嘿,谢谢你的精彩评论-@Prune我问了,因为我认为社区中的人会知道也不知道如何使用dis
函数来查找说明。至于不担心作业时间,我同意,但问题来了,我很好奇。对于大文件或大量文件来说,这可能会有一点不同。如果您关心像这样的小情况下的性能,Nuitka和Cython可以编译和优化纯python代码,使之更快。
>>> def get_text(filename):
... with open(filename, 'rb') as f:
... text = pickle.load(f)
... return text
...
>>> def get_text2(filename):
... with open(filename, 'rb') as f:
... return pickle.load(f)
...
>>> import dis
>>> dis.dis(get_text)
2 0 LOAD_GLOBAL 0 (open)
2 LOAD_FAST 0 (filename)
4 LOAD_CONST 1 ('rb')
6 CALL_FUNCTION 2
8 SETUP_WITH 16 (to 26)
10 STORE_FAST 1 (f)
3 12 LOAD_GLOBAL 1 (pickle)
14 LOAD_METHOD 2 (load)
16 LOAD_FAST 1 (f)
18 CALL_METHOD 1
20 STORE_FAST 2 (text)
22 POP_BLOCK
24 LOAD_CONST 0 (None)
>> 26 WITH_CLEANUP_START
28 WITH_CLEANUP_FINISH
30 END_FINALLY
4 32 LOAD_FAST 2 (text)
34 RETURN_VALUE
>>> dis.dis(get_text2)
2 0 LOAD_GLOBAL 0 (open)
2 LOAD_FAST 0 (filename)
4 LOAD_CONST 1 ('rb')
6 CALL_FUNCTION 2
8 SETUP_WITH 12 (to 22)
10 STORE_FAST 1 (f)
3 12 LOAD_GLOBAL 1 (pickle)
14 LOAD_METHOD 2 (load)
16 LOAD_FAST 1 (f)
18 CALL_METHOD 1
20 RETURN_VALUE
>> 22 WITH_CLEANUP_START
24 WITH_CLEANUP_FINISH
26 END_FINALLY
28 LOAD_CONST 0 (None)
30 RETURN_VALUE