Python中单个与多个for循环的区别?

4 投票
3 回答
1045 浏览
提问于 2025-04-16 18:33

在比较以下的 python 代码示例时(这里的 300 只是个例子;实际上,假设我们需要循环处理 10,000,000 个项目):

sum = 0
for i in xrange(0, 300):
    sum += i

sum = 0
for i in xrange(0, 100):
    sum += i
for i in xrange(100, 200):
    sum += i
for i in xrange(200, 300):
    sum += i

这两个版本在运行时间上是一样的吗?我遇到一个问题,我有一个很大的向量(比如说,有 10,000 个项目)。我不一定需要遍历所有的项目,除非满足某些条件(这些条件只能在第一个循环完成后才能评估,这个循环是使用前 100 个项目)。

然后,只有在满足某些条件的情况下,我才应该继续循环(这些条件只能在检查下一个 100 个项目时评估)。

同样的情况,直到我到达向量的末尾................

考虑到我可以通过检查以下点以模块化的方式解决我的问题:

{0, 100} {100, 200} {200, 300} ........ {9900, 10,000}

我只是想了解第二种方法是否和第一种方法一样高效。谢谢。

注意:这里使用 sum 是为了简单起见。实际上,所用数学运算的运行时间要大得多。这就是为什么我试图通过检查不同的编码方法来优化运行时间...

3 个回答

1

如果你想比较速度,可以直接给它们计时:

import timeit

chunk1 = '''
sum = 0
for i in xrange(0, 300):
    sum += i
'''

chunk2 = '''
sum = 0
for i in xrange(0, 100):
    sum += i
for i in xrange(100, 200):
    sum += i
for i in xrange(200, 300):
    sum += i
'''

timer1 = timeit.Timer(chunk1)
timer2 = timeit.Timer(chunk2)

print timer1.timeit(100000)
print timer2.timeit(100000)

我在进行 100,000 次循环时得到了这些数字:

3.44955992699
3.56597089767

从结果来看,第二段代码稍微慢了一点。


你可以试试用 while 循环和 break 语句,所以我理解你想做的是这个:

i = 0

while i < limit:
  stop = False

  for j in xrange(i + 100, i + 300):
    if i == foo:
      stop = True
      break

  if stop:  break
  i += 1
1

如果你不打算遍历所有的内容,那么创建一个新的生成器(xrange)的开销是非常小的。

所以,如果你有时会跳过一两个循环,第二种方法会更快。

不过,如果你的列表只有300个元素,那么这个差别就几乎可以忽略不计,可能只是几毫秒或微秒的差别。

5

你希望看到什么样的改进呢?

timeit可以帮助你观察不同之处:

$ python -m timeit 'sum = 0
> for i in xrange(0, 300):
>     sum += i'
10000 loops, best of 3: 21.8 usec per loop

$ python -m timeit 'sum = 0
> for i in xrange(0, 100):
>     sum += i
> for i in xrange(100, 200):
>     sum += i
> for i in xrange(200, 300):
>     sum += i'
10000 loops, best of 3: 22.8 usec per loop

就我个人而言,我会选择:

$ python -m timeit 'sum(xrange(300))'
100000 loops, best of 3: 5.34 usec per loop

这个例子可能不是评估你是否能优化自己代码的最佳方式,但它确实展示了如何测试一小段代码的运行时间。

记得唐纳德·克努斯关于优化的说法哦 ;-)

这里有一种方法可以让你在迭代时设置检查点,如果需要的话可以中断:

>>> for index, item in enumerate(vect):
...     results = do_stuff_with(item)
...     if index % 100 == 0 and should_we_stop(results):
...         break

更好的做法是让do_stuff_with()返回一个tuple,指示它是否完成,这样你就可以在每一次迭代中检查是否完成,而不是一直等着:

>>> for item in vect:
...     finished, results = do_stuff_with(item)
...     if finished:
...         break

再强调一下(不是双关),在没有看到你实际代码的情况下,很难说如何(甚至是否)优化你的代码!

撰写回答