如何在传递变量给函数时使用python timeit?
我在使用timeit的时候遇到了一些困难,想问问有没有人能给点建议。
简单来说,我有一个函数(我会给它传一个值),我想测试一下这个函数的运行速度,所以我写了这个:
if __name__=='__main__':
from timeit import Timer
t = Timer(superMegaIntenseFunction(10))
print t.timeit(number=1)
但是当我运行它的时候,出现了一些奇怪的错误,像是来自timeit模块的错误:
ValueError: stmt is neither a string nor callable
如果我单独运行这个函数,它是没问题的。问题出在我把它放进timeit模块里时,就出现了错误(我试过用双引号和不用双引号,结果都是一样的)。
如果能给点建议就太好了!
谢谢!
5 个回答
你应该传递一个字符串。也就是说,
t = Timer('superMegaIntenseFunction(10)','from __main__ import superMegaIntenseFunction')
Timer(superMegaIntenseFunction(10))
的意思是“先调用 superMegaIntenseFunction(10)
,然后把结果传给 Timer
”。这显然不是你想要的。Timer
期待的是一个可调用的东西(听起来就是可以被调用的东西,比如一个函数),或者一个字符串(这样它可以把字符串里的内容当作 Python 代码来理解)。Timer
的工作原理是反复调用这个可调用的东西,看看需要多长时间。
Timer(superMegaIntenseFunction)
这个写法是可以通过类型检查的,因为 superMegaIntenseFunction
是可调用的。但是,Timer
不知道该给 superMegaIntenseFunction
传什么值。
解决这个问题的简单方法是使用一个包含代码的字符串。我们需要给代码传递一个“setup”参数,因为这个字符串是在一个新的环境中“被解释为代码”的——它无法访问相同的 globals
,所以你需要运行另一段代码来让定义可用——可以参考 @oxtopus 的回答。
通过 lambda
(就像 @Pablo 的回答中提到的),我们可以把参数 10
绑定到调用 superMegaIntenseFunction
上。我们所做的就是创建另一个不需要参数的函数,然后用 10
调用 superMegaIntenseFunction
。这就像你用 def
创建了另一个这样的函数,只不过这个新函数没有名字(因为它不需要名字)。
把它变成可以调用的:
if __name__=='__main__':
from timeit import Timer
t = Timer(lambda: superMegaIntenseFunction(10))
print(t.timeit(number=1))
应该可以正常工作