11

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

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

我想测试这个函数在一个随机数组上运行需要多长时间,我希望在 timeit 测试之外生成它。换句话说,我不想将生成数组所需的时间包含在时​​间中。

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

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

但这给了我一个错误: NameError: global name 'x' is not defined

我怎样才能做到这一点?

4

5 回答 5

22

Import x from __main__ as well:

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

Just like function, x is a name in the __main__ module, and can be imported into the timeit setup.

于 2013-09-18T21:36:48.473 回答
12

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

timeit.timeit(lambda: function(x))

或者,如果您愿意:

timeit.timeit(partial(function, x))

(详见这里。注意它需要 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,这种差异就会越小。

于 2013-09-18T21:38:39.503 回答
3

进口x__main__

timeit.timeit("function(x)",setup="from __main__ import function, x")
于 2013-09-18T21:36:56.130 回答
0

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

所以不要写:

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

...你现在可以写:

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

于 2018-01-01T20:33:43.277 回答
0

或者,您可以添加xglobals. 它的好处是它可以在pdb调试会话中工作:

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

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

于 2017-02-09T02:20:29.793 回答