例如,我有一个列表:
L=[-13, -24, -21, -3, -23, -15, -14, -27, -13, -12]
如果输入%timeit -n 10 myList = [item for item in L if item < 15]
输出为10 loops, best of 3: 1.25 µs per loop
如果我输入myGen = (item for item in L if item < 15)
输出为1000000 loops, best of 3: 561 ns per loop
我不理解案例2,为什么一个发生器需要1000000个循环而不是10个循环?什么是最好的3&#34;意思?如何计算每个通道所需的总秒数,例如10 * 1.25 = 12.5 us对于情况1?
答案 0 :(得分:5)
在第二个示例中,您没有将-n
参数包含在%timeit
中,因此ipython会根据试运行的时间长短来改变重复次数;测试代码越快,迭代次数越多,每次迭代时间值就越准确。
此外,测试运行多次以尝试并最小化外部因素(例如,当您的操作系统恰好安排磁盘缓冲区刷新而其他所有内容变得有点慢)。这就是'最好的3'的来源;测试连续运行3次,并选择最佳时间。
请参阅%timeit
magic command documentation,其中包含以下选项及其默认行为:
-n<N>
:在循环中执行给定语句<N>
次。如果未给出该值,则选择拟合值。
-r<R>
:重复循环迭代<R>
次并获得最佳结果。默认值:3
您的第一个示例 使用-n 10
,因此它只运行了10次。
因为使用生成器表达式创建生成器对象几乎是即时的,所以ipython可以比执行列表推导更加频繁地执行循环方式(必须执行for
循环和生成一个列表对象,其中包含所有结果然后)。请记住,在驱动迭代之前,生成器表达式不会执行任何工作。
如果要比较生成器表达式生成与列表推导相同的结果所需的时间,则必须实际迭代。您可以将表达式传递给list()
调用以实际生成列表:
%timeit -n 10 myGen = (item for item in L if item < 15); list(myGen)
这会慢,因为生成器比列表理解有更多的开销:
In [1]: L=[-13, -24, -21, -3, -23, -15, -14, -27, -13, -12]
In [2]: %timeit -n 10 myList = [item for item in L if item < 15]
10 loops, best of 3: 1.29 µs per loop
In [3]: %timeit -n 10 myGen = (item for item in L if item < 15); list(myGen)
10 loops, best of 3: 1.72 µs per loop
请注意,有在每次测试迭代时重新创建生成器,因为生成器只能生成一次输出。