我有以下两个功能:
def foo(n=50000):
return sum(i*i for i in range(n)) # just called sum() directly without
def bar(n=50000):
return sum([i*i for i in range(n)]) # passed constructed list to sum()
我希望foo
的运行速度会比bar
更快,但我已经使用%%timeit
检查了ipython foo
的时间稍长于bar
< / p>
In [2]: %%timeit
...: foo(50000)
...:
100 loops, best of 3: 4.22 ms per loop
In [3]: %%timeit
...: bar(50000)
...:
100 loops, best of 3: 3.45 ms per loop
In [4]: %%timeit
...: foo(10000000)
...:
1 loops, best of 3: 1.02 s per loop
In [5]: %%timeit
...: bar(10000000)
...:
1 loops, best of 3: 869 ms per loop
随着我增加n的值,差异会增加,因此我尝试使用dis.dis(foo)
和dis.dis(bar)
检查功能,但它是相同的。
那么两种方法之间存在这种时差的原因是什么?
答案 0 :(得分:6)
关于发电机有很多很好的答案,所以我不会详细说明。
生成器保持状态。如果你进行快速操作(例如使用sum
),它们会稍慢一些,但是如果你使用I / O命令就会有很大的不同。
生成器的好处是他们不会提前将所有项目加载到内存,列表就是这样。
当您迭代列表时(在非常高级别中)会发生这种情况:
将其与发电机进行比较:
中间的这个额外步骤是测试中的差异。
因此,生成器通常用于处理需要加载到内存的巨大数据量。 (对于协同程序的生成器,有更多用例)
使用大文件和for循环打印行进行过期。在某些时候,使用列表时会出现内存不足的情况。然后尝试使用发电机,他们不会失去记忆......