在Python中分配变量的时间到了
假设我有一个非常紧密的循环:在Python中分配变量的时间到了,python,variables,variable-assignment,assign,Python,Variables,Variable Assignment,Assign,假设我有一个非常紧密的循环: a = func(x) b = func2(a) 变量a不在其他任何地方使用 Python是自动将赋值编译成a,还是每次都要花时间进行变量赋值?换句话说,这个代码是相同的,还是由于没有分配给a,所以速度稍微快了一点 b = func2(func(x)) Python2.7与Python3的行为相同吗?这种类型的查询可以通过timeit轻松检查。下面是Python2.7的结果 root:/var# python -m timeit "f1 = lambda x:x
a = func(x)
b = func2(a)
变量a
不在其他任何地方使用
Python是自动将赋值编译成a
,还是每次都要花时间进行变量赋值?换句话说,这个代码是相同的,还是由于没有分配给a
,所以速度稍微快了一点
b = func2(func(x))
Python2.7与Python3的行为相同吗?这种类型的查询可以通过
timeit
轻松检查。下面是Python2.7的结果
root:/var# python -m timeit "f1 = lambda x:x; f2 = lambda x: x*2; a=f1(2); b=f2(a)"
1000000 loops, best of 3: 0.29 usec per loop
root:/var# python -m timeit "f1 = lambda x:x; f2 = lambda x: x*2; b=f2(f1(2))"
1000000 loops, best of 3: 0.284 usec per loop
root:/var# python -m timeit "f1 = lambda x:x; f2 = lambda x: x*2; a=f1(2); b=f2(a)"
1000000 loops, best of 3: 0.285 usec per loop
root:/var# python -m timeit "f1 = lambda x:x; f2 = lambda x: x*2; b=f2(f1(2))"
1000000 loops, best of 3: 0.283 usec per loop
root:/var# python -m timeit "f1 = lambda x:x; f2 = lambda x: x*2; a=f1(2); b=f2(a)"
1000000 loops, best of 3: 0.294 usec per loop
root:/var# python -m timeit "f1 = lambda x:x; f2 = lambda x: x*2; b=f2(f1(2))"
1000000 loops, best of 3: 0.286 usec per loop
这显示了与描述awesome
dis
模块使用情况的其他答案一致的结果。此类查询可以通过timeit
轻松检查。下面是Python2.7的结果
root:/var# python -m timeit "f1 = lambda x:x; f2 = lambda x: x*2; a=f1(2); b=f2(a)"
1000000 loops, best of 3: 0.29 usec per loop
root:/var# python -m timeit "f1 = lambda x:x; f2 = lambda x: x*2; b=f2(f1(2))"
1000000 loops, best of 3: 0.284 usec per loop
root:/var# python -m timeit "f1 = lambda x:x; f2 = lambda x: x*2; a=f1(2); b=f2(a)"
1000000 loops, best of 3: 0.285 usec per loop
root:/var# python -m timeit "f1 = lambda x:x; f2 = lambda x: x*2; b=f2(f1(2))"
1000000 loops, best of 3: 0.283 usec per loop
root:/var# python -m timeit "f1 = lambda x:x; f2 = lambda x: x*2; a=f1(2); b=f2(a)"
1000000 loops, best of 3: 0.294 usec per loop
root:/var# python -m timeit "f1 = lambda x:x; f2 = lambda x: x*2; b=f2(f1(2))"
1000000 loops, best of 3: 0.286 usec per loop
这显示了与其他描述使用awesomedis
模块的答案一致的结果。因此,使用非常有趣的模块,我们可以查看从您提供的python代码生成的实际字节码。为了简单起见,我将func
和func2
替换为内置函数(int
和float
)
因此,我们的来源如下:
def assign():
a = int()
b = float(a)
与简化版本相比:
def simple():
b = float(int())
然后从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
如您所见,与简化的`简单方法的字节码相比,没有对窥视孔进行优化以删除不必要的中间变量,这导致额外的2条指令(STORE\u FAST a
,LOAD\u 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
这与Python解释器(用于Python 3.5)和Python解释器(用于Python 2.7)的情况相同。因此,使用非常有趣的模块,我们可以查看从您提供的Python代码生成的实际字节码。为了简单起见,我将func
和func2
替换为内置函数(int
和float
)
因此,我们的来源如下:
def assign():
a = int()
b = float(a)
与简化版本相比:
def simple():
b = float(int())
然后从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
如您所见,与简化的`简单方法的字节码相比,没有对窥视孔进行优化以删除不必要的中间变量,这导致额外的2条指令(STORE\u FAST a
,LOAD\u 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
这与Python解释器(用于Python 3.5)和Python解释器(用于Python 2.7)的情况相同。使用dis模块比较字节码:看起来第二种方法产生的操作更少
使用dis模块比较字节码:看起来第二种方法产生的操作更少
实际时间取决于函数
func()
和func2()
do。这不是最好的示例,但下面给出了一个快速(且不干净)的测试代码:
import time
def func(x):
return 5
def func2(a):
return 10
t0 = time.time()
x = 10
for i in range(1,10000):
a = func(x)
b = func2(a)
t1 = time.time()
print("Time 1: ", t1-t0)
t2 = time.time()
x = 10
for i in range(1,10000):
b = func2(func(x))
t3 = time.time()
print("Time 2: ", t3-t2)
上述代码的输出为:
Time 1: 0.0029211044311523438
Time 2: 0.002785921096801758
因此是的,在Pyhton 3中,我们避免分配
a
的实现稍微快一些。实际时间将取决于函数func()
和func2()
do。这不是最好的示例,但下面给出了一个快速(且不干净)的测试代码:
import time
def func(x):
return 5
def func2(a):
return 10
t0 = time.time()
x = 10
for i in range(1,10000):
a = func(x)
b = func2(a)
t1 = time.time()
print("Time 1: ", t1-t0)
t2 = time.time()
x = 10
for i in range(1,10000):
b = func2(func(x))
t3 = time.time()
print("Time 2: ", t3-t2)
上述代码的输出为:
Time 1: 0.0029211044311523438
Time 2: 0.002785921096801758
是的,在Pyton 3中,我们避免分配
a
的实现稍微快一点。不确定,但如果没有分配,可能会快一点。这似乎是一个你可以自己尝试回答的问题(例如,使用模块)@larsks我读到,timeit
对于如此小的时差有些不可靠。下面所有使用它的答案都显示了纳秒级的差异,这并不令人信服,可能只是噪音。字节码答案是我一直在寻找的答案(我以前不知道dis),对此不确定,但如果没有作业,可能会更快。这似乎是一个你可以自己尝试回答的问题(例如,使用模块)@larsks我读到,timeit
对于如此小的时差有些不可靠。下面所有使用它的答案都显示了纳秒级的差异,这并不令人信服,可能只是噪音。字节码答案是我一直在寻找的答案(我以前不知道dis
),将f1
和f2
的创建放在设置块中而不是放在计时循环中可能更有意义。同意。无需为每次迭代进行初始化。将f1
和f2
的创建放在设置块中,而不是放在计时循环中可能更有意义。同意。每次迭代都不需要初始化。与@MatthewStory的答案基本相同,但显示了不同的使用dis.dis
-除非我得到一些否定的回答,否则我将保留它。与@MatthewStory的答案基本相同,但显示了不同的使用dis.dis
-除非我得到一些否定的回答,否则我将保留它否定回答。为什么会取决于具体的功能?对不起,我的意思是,实际的时间将取决于功能的内容。编辑了回复。为什么会取决于具体的功能?对不起,我的意思是,实际的时间将取决于功能的内容。编辑了回复。