我意识到Python并不是性能最好的语言,但是因为这看起来很容易,我想知道如果我有嵌套循环,是否值得在for循环之外移动范围赋值。例如:
for i in range(1000):
for j in range(1000):
foo()
与
r = range(1000)
for i in range(1000):
for j in r:
foo()
第二个运行速度会更快,或者Python解释器会在第一个示例中优化重复的函数调用吗?另外,如果我使用xrange,答案会改变吗? (或Python 3范围)。谢谢!
答案 0 :(得分:3)
让我们看看:
@timeit
def a():
x = 0
for i in range(10000):
for j in range(10000):
x+=1
return x
@timeit
def b():
x = 0
r = range(10000)
for i in range(10000):
for j in r:
x+=1
return x
a()
b()
'a' ((), {}) 3.30 sec
'b' ((), {}) 2.64 sec
所以是的,第二个看起来更快。
答案 1 :(得分:1)
延伸@Hrvoje的回答,这是我的基准:
import timeit
NUM_ITERATIONS = 5000
NUM_BENCHMARKS = 50
def a():
x = 0
for i in range(NUM_ITERATIONS):
for j in range(NUM_ITERATIONS):
x+=1
return x
def b():
x = 0
r = range(NUM_ITERATIONS)
for i in range(NUM_ITERATIONS):
for j in r:
x+=1
return x
def c():
x = 0
r1 = range(NUM_ITERATIONS)
r2 = range(NUM_ITERATIONS)
for i in r1:
for j in r2:
x+=1
return x
def d():
x = 0
for i in xrange(NUM_ITERATIONS):
for j in xrange(NUM_ITERATIONS):
x += 1
return x
def e():
x = 0
r = xrange(NUM_ITERATIONS)
for i in xrange(NUM_ITERATIONS):
for j in r:
x += 1
return x
print "A: %.4f" % (timeit.timeit(a, number=NUM_BENCHMARKS))
print "B: %.4f" % (timeit.timeit(b, number=NUM_BENCHMARKS))
print "C: %.4f" % (timeit.timeit(c, number=NUM_BENCHMARKS))
print "D: %.4f" % (timeit.timeit(d, number=NUM_BENCHMARKS))
print "E: %.4f" % (timeit.timeit(e, number=NUM_BENCHMARKS))
结果:
A: 81.5383
B: 71.2025
C: 69.2143
D: 94.8806
E: 93.1961
非常符合预期。使用xrange
并没有真正的区别,因为它正在返回一个生成器。预定义范围变量的好处很明显。
答案 2 :(得分:0)
我得到的结果非常不确定
In [1]: def f():
...: for i in range(1000):
...: for j in range(1000):
...: pass
...:
In [2]: def g():
...: r = range(1000)
...: for i in range(1000):
...: for j in r:
...: pass
...:
In [3]: import itertools
In [4]: def h():
...: for i in itertools.product(range(1000),range(1000)):
...: pass
In [6]: timeit f()
10 loops, best of 3: 23.6 ms per loop
In [7]: timeit g()
10 loops, best of 3: 22.9 ms per loop
In [8]: timeit h()
10 loops, best of 3: 38.3 ms per loop
我认为这个故事的寓意是“不要使用itertools,那个慢了”#34;
(Python 3,所以范围是这里的生成器)