how to pass parameters of a function when using timeit.Timer()
这是一个简单程序的大纲
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # some pre-defined constants A = 1 B = 2 # function that does something critical def foo(num1, num2): # do something # main program.... do something to A and B for i in range(20): # do something to A and B # and update A and B during each iteration import timeit t = timeit.Timer(stmt="foo(num1,num2)") print t.timeit(5) |
我只是不断地得到"全球名称foo没有定义"……有人能帮我吗?谢谢!
函数可以使用
1 2 3 4 5 6 7 8 9 10 11 12 | def foo(num1, num2): def _foo(): # do something to num1 and num2 pass return _foo A = 1 B = 2 import timeit t = timeit.Timer(foo(A,B)) print t.timeit(5) |
或者更短,我们可以使用functools.partial而不是显式闭包声明
1 2 3 4 5 6 7 8 9 10 | def foo(num1, num2): # do something to num1 and num2 pass A = 1 B = 2 import timeit, functools t = timeit.Timer(functools.partial(foo, A, B)) print t.timeit(5) |
假设您的模块文件名是test.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # some pre-defined constants A = 1 B = 2 # function that does something critical def foo(n, m): pass # main program.... do something to A and B for i in range(20): pass import timeit t = timeit.Timer(stmt="test.foo(test.A, test.B)", setup="import test") print t.timeit(5) |
代码段必须是自包含的-它们不能进行外部引用。必须在语句字符串或设置字符串中定义值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import timeit setup =""" A = 1 B = 2 def foo(num1, num2): pass def mainprog(): global A,B for i in range(20): # do something to A and B foo(A, B) """ t = timeit.Timer(stmt="mainprog()" setup=setup) print(t.timeit(5)) |
更好的是,重写代码以不使用全局值。
您的函数需要在设置字符串中定义。实现这一点的一个好方法是在模块中设置代码,因此您只需
1 2 | t = timeit.Timer("foo(num1, num2)","from myfile import foo") t.timeit(5) |
否则,您必须将所有设置定义为SETUP语句中的字符串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | setup =""" # some pre-defined constants A = 1 B = 2 # function that does something critical def foo(num1, num2): # do something # main program.... do something to A and B for i in range(20): # do something to A and B # and update A and B during each iteration """ t = timeit.Timer("foo(num1, num2)", setup) t.timeit(5) |
我刚刚发现的一个很棒的东西是ipython使用cprofile的快捷方式。
1 2 3 4 | def foo(x, y): print x*y %prun foo("foo", 100) |
我通常会创建一个额外的函数:
1 2 3 4 5 6 7 8 9 10 | def f(x,y): return x*y v1 = 10 v2 = 20 def f_test(): f(v1,v2) print(timeit.timeit("f_test()", setup="from __main__ import f_test")) |
有一个更简单的解决方案(至少对于Python3),您可以使代码在当前全局命名空间中执行:
https://docs.python.org/3/library/timeit.html示例我知道全局参数不是首选,但是如果您只是制作一个快速脚本来检查某些东西,我认为这是最简单的实现。
下面是一个如何划分计时例程而不调用全局的示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | def foo(a, b): '''Do something to `a` and `b`''' return a + b def time_foo(): '''Create timer object simply without using global variables''' import timeit _foo = foo a = 1 b = 2 # Get `Timer` oject, alternatively just get time with `timeit.timeit()` t = timeit.Timer('_foo(a, b)', globals=locals()) return t |
如果要使用同一个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | def foo1(a, b): '''Add `a` and `b`''' return a + b def foo2(a, b): '''More math on `a` and `b`''' return (a**2 * b)**2 def time_foo(func, **kwargs): '''Create timer object simply without using global variables''' import timeit return timeit.timeit('func(**kwargs)', globals=locals()) def run(): '''Modify inputs to foo and see affect on execution time''' a = 1 b = 2 for i in range(10): # Update `a` and `b` a += 1 b += 2 # Pass args to foo as **kwargs dict print('foo1 time: ', time_foo(foo1, **{'a':a, 'b':b})) print('foo2 time: ', time_foo(foo2, **{'a':a, 'b':b})) return None |
今天我在python3.7中玩计时,试图将函数和变量传递到计时器中。这就是我想到的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | import re text ="This is a test of the emergency broadcast system" def regex(text): return re.sub(r"(\s)\1{1,}", r"\1", text) def loop_while(text): if" " in text: while" " in text: text = text.replace(" ","") return text if __name__ =="__main__": import timeit callable_functions = [item for item in locals().items() if callable(item[1])] for func_name, func in callable_functions: elapsed_time = timeit.timeit(f"{func_name}(text)", globals=globals(), number=100000) print(f"{func_name}: {elapsed_time} {func(text)} ") |
此输出:
regex: 1.378352418
This is a test of the emergency broadcast systemloop_while: 0.15858950299999997
This is a test of the emergency
broadcast system
然后测试一个新版本所需要的就是添加一个新的函数。类似:
1 2 | def split_join(text): return"".join(text.split()) |
现在它输出:
regex: 1.378352418
This is a test of the emergency broadcast systemloop_while: 0.15858950299999997
This is a test of the emergency broadcast systemsplit_join: 0.05700970800000005
This is a test of the emergency broadcast system
这应该有效:
1 2 3 4 5 6 7 8 9 10 11 | import timeit def f(x,y): return x*y x = 5 y = 7 print(timeit.timeit(stmt='f(x,y)', setup='from __main__ import f, x, y', number=1000)) |
我更喜欢创建一个
Another note, it is better to do test runs in function rather then in the global space, as the global space isn't taking advantage of
FAST_LOAD Why does Python code run faster in a function?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class Data(object): """Data Creation""" x = [i for i in range(0, 10000)] y = tuple([i for i in range(0, 10000)]) def __init__(self): pass import timeit def testIterator(x): for i in range(10000): z = i print timeit.timeit("testIterator(Data.x)", setup="from __main__ import testIterator, Data", number=50) print timeit.timeit("testIterator(Data.y)", setup="from __main__ import testIterator, Data", number=50) |