使用timeit时如何传递函数的参数.Timer()

时间:2021-05-28 18:04:19

This is the outline of a simple program

这是一个简单程序的概述

# 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)

I just keep getting "global name foo is not defined"..... Can anyone help me on this? Thanks!

我只是不断得到“全球名称foo没有定义”.....任何人都可以帮我这个吗?谢谢!

9 个解决方案

#1


11  

The code snippets must be self-contained - they cannot make external references. You must define your values in the statement-string or setup-string:

代码片段必须是自包含的 - 它们不能进行外部引用。您必须在statement-string或setup-string中定义值:

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))

Better yet, rewrite your code to not use global values.

更好的是,重写代码以不使用全局值。

#2


27  

The functions can use arguments in timeit if these are created using closures, we can add this behaviours by wrapping them in another function.

如果使用闭包创建这些函数,函数可以在timeit中使用参数,我们可以通过将它们包装在另一个函数中来添加这些行为。

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)

or shorter, we can use functools.partial instead of explicit closures declaration

或者更短,我们可以使用functools.partial而不是显式闭包声明

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)

#3


13  

Supposing that your module filename is test.py

假设您的模块文件名是test.py

# 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)

#4


9  

Your function needs to be define in the setup string. A good way to do this is by setting up your code in a module, so you simple have to do

您的功能需要在设置字符串中定义。执行此操作的一种好方法是在模块中设置代码,这样您就可以轻松完成

t = timeit.Timer("foo(num1, num2)", "from myfile import foo")
t.timeit(5)

Otherwise, you'll have to define all of the setup as a string inside the setup statement.

否则,您必须将所有设置定义为setup语句中的字符串。

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)

Something awesome I just found out about is a shortcut for iPython that uses cProfile.

我刚刚发现的一些令人敬畏的东西是使用cProfile的iPython的快捷方式。

def foo(x, y):
    print x*y

%prun foo("foo", 100)

#5


8  

I usually create an extra function:

我通常创建一个额外的功能:

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"))

#6


1  

Here is an example of how to compartmentalize the timing routine, without calling globals

下面是一个如何在不调用全局变量的情况下划分定时例程的示例

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

You could even generalize this if you wanted to use the same timeit function to time other functions. Here is an example with your example main() routine:

如果您想使用相同的timeit函数来计时其他函数,您甚至可以概括这一点。以下是您的示例main()例程的示例:

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

#7


1  

There is a much simpler solution (at least for Python 3), you can cause the code to be executed within your current global namespace:

有一个更简单的解决方案(至少对于Python 3),您可以使代码在当前的全局命名空间中执行:

t = timeit.Timer(stmt="foo(num1,num2)", globals=globals())

t = timeit.Timer(stmt =“foo(num1,num2)”,globals = globals())

https://docs.python.org/3/library/timeit.html#examples I know globals are not preferred, but if you are just making a quick script to check something I think this is the easiest implementation.

https://docs.python.org/3/library/timeit.html#examples我知道全局变量不是首选,但如果您只是制作快速脚本来检查某些内容,我认为这是最简单的实现。

#8


0  

I prefer creating a static class with all the Data ready to be picked up prior of running the timer.

我更喜欢创建一个静态类,所有数据都准备好在运行计时器之前被选中。

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?

另外需要注意的是,最好是在函数中进行测试运行,而不是在全局空间中运行,因为全局空间没有利用FAST_LOAD为什么Python代码在函数中运行得更快?

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)

#9


0  

This should work:

这应该工作:

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))

#1


11  

The code snippets must be self-contained - they cannot make external references. You must define your values in the statement-string or setup-string:

代码片段必须是自包含的 - 它们不能进行外部引用。您必须在statement-string或setup-string中定义值:

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))

Better yet, rewrite your code to not use global values.

更好的是,重写代码以不使用全局值。

#2


27  

The functions can use arguments in timeit if these are created using closures, we can add this behaviours by wrapping them in another function.

如果使用闭包创建这些函数,函数可以在timeit中使用参数,我们可以通过将它们包装在另一个函数中来添加这些行为。

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)

or shorter, we can use functools.partial instead of explicit closures declaration

或者更短,我们可以使用functools.partial而不是显式闭包声明

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)

#3


13  

Supposing that your module filename is test.py

假设您的模块文件名是test.py

# 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)

#4


9  

Your function needs to be define in the setup string. A good way to do this is by setting up your code in a module, so you simple have to do

您的功能需要在设置字符串中定义。执行此操作的一种好方法是在模块中设置代码,这样您就可以轻松完成

t = timeit.Timer("foo(num1, num2)", "from myfile import foo")
t.timeit(5)

Otherwise, you'll have to define all of the setup as a string inside the setup statement.

否则,您必须将所有设置定义为setup语句中的字符串。

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)

Something awesome I just found out about is a shortcut for iPython that uses cProfile.

我刚刚发现的一些令人敬畏的东西是使用cProfile的iPython的快捷方式。

def foo(x, y):
    print x*y

%prun foo("foo", 100)

#5


8  

I usually create an extra function:

我通常创建一个额外的功能:

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"))

#6


1  

Here is an example of how to compartmentalize the timing routine, without calling globals

下面是一个如何在不调用全局变量的情况下划分定时例程的示例

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

You could even generalize this if you wanted to use the same timeit function to time other functions. Here is an example with your example main() routine:

如果您想使用相同的timeit函数来计时其他函数,您甚至可以概括这一点。以下是您的示例main()例程的示例:

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

#7


1  

There is a much simpler solution (at least for Python 3), you can cause the code to be executed within your current global namespace:

有一个更简单的解决方案(至少对于Python 3),您可以使代码在当前的全局命名空间中执行:

t = timeit.Timer(stmt="foo(num1,num2)", globals=globals())

t = timeit.Timer(stmt =“foo(num1,num2)”,globals = globals())

https://docs.python.org/3/library/timeit.html#examples I know globals are not preferred, but if you are just making a quick script to check something I think this is the easiest implementation.

https://docs.python.org/3/library/timeit.html#examples我知道全局变量不是首选,但如果您只是制作快速脚本来检查某些内容,我认为这是最简单的实现。

#8


0  

I prefer creating a static class with all the Data ready to be picked up prior of running the timer.

我更喜欢创建一个静态类,所有数据都准备好在运行计时器之前被选中。

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?

另外需要注意的是,最好是在函数中进行测试运行,而不是在全局空间中运行,因为全局空间没有利用FAST_LOAD为什么Python代码在函数中运行得更快?

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)

#9


0  

This should work:

这应该工作:

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))