Python:有没有办法使用timeit.timeit()导入变量?

时间:2013-09-18 21:34:43

标签: python time timeit

假设我有一些函数接受一个数组并将每个元素都改为0。

def function(array):
    for i in range(0,len(array)):
        array[i] = 0
return array

我想测试这个函数在随机数组上运行多长时间,我想生成timeit测试的OUTSIDE。换句话说,我不希望将生成数组所花费的时间包括在内。

我首先将一个随机数组存储在变量x中并执行:

timeit.timeit("function(x)",setup="from __main__ import function")

但这给了我一个错误:NameError:全局名称'x'未定义

我该怎么做?

5 个答案:

答案 0 :(得分:20)

x 导入__main__以及

timeit.timeit("function(x)", setup="from __main__ import function, x")

function一样,x__main__模块中的名称,可以导入timeit设置。

答案 1 :(得分:11)

如果您传递timeit函数而不是字符串,则可以完全避免此问题。在这种情况下,函数在其正常的全局和闭包环境中执行。所以:

timeit.timeit(lambda: function(x))

或者,如果您愿意:

timeit.timeit(partial(function, x))

(有关详细信息,请参阅here。请注意,它需要Python 2.6+,因此如果您需要2.3-2.5,则无法使用此技巧。)


正如文档所说,“请注意,由于额外的函数调用,在这种情况下,时序开销会略大一些。”

这意味着它使timeit本身运行得更慢。例如:

>>> def f(): pass
>>> timeit.timeit('timeit.timeit("f()", setup="from __main__ import f")', setup='import timeit', number=1000)
91.66315175301861
>>> timeit.timeit(lambda: timeit.timeit(f), number=100)
94.89793294097762

但是,它不会影响实际结果:

>>> timeit.timeit(f, number=100000000)
8.81197881908156
>>> timeit.timeit('f()', setup='from __main__ import f', number=100000000)
8.893913001054898

(在极少数情况下,这通常意味着一个版本或另一个版本没有像在实际代码中调用函数一样测试函数,或者测试错误的闭包或类似函数。)

请注意,此处函数内部的实际时间约为88秒,因此我们几乎将时序代码的开销增加了一倍......但它仍然只增加了3%的总测试时间。而不那么微不足道的f,这个差异就越小。

答案 2 :(得分:3)

x导入__main__

timeit.timeit("function(x)",setup="from __main__ import function, x")

答案 3 :(得分:0)

或者,您可以将x添加到globals。它的好处是它可以在pdb调试会话中运行:

globals()['x'] = x
timeit.timeit(lambda: function(x))
  

请注意,由于额外的函数调用,在这种情况下,时序开销会略大一些。 [source]

答案 4 :(得分:0)

使用Python 3.5,引入了可选参数globals。 它可以指定执行timeit语句的命名空间。

所以不要写:

timeit.timeit("function(x), setup="from __main__ import function, x")

...你现在可以写:

timeit.timeit("function(x)", globals=globals())