我应该在Python中指定循环之外的范围吗?

时间:2015-07-07 00:05:52

标签: python performance

我意识到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范围)。谢谢!

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,所以范围是这里的生成器)