Python中单个与多个for循环的区别?
在比较以下的 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 个回答
如果你想比较速度,可以直接给它们计时:
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
如果你不打算遍历所有的内容,那么创建一个新的生成器(xrange
)的开销是非常小的。
所以,如果你有时会跳过一两个循环,第二种方法会更快。
不过,如果你的列表只有300个元素,那么这个差别就几乎可以忽略不计,可能只是几毫秒或微秒的差别。
你希望看到什么样的改进呢?
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
再强调一下(不是双关),在没有看到你实际代码的情况下,很难说如何(甚至是否)优化你的代码!