how to pass parameters of a function when using ti

2020-02-16 08:34发布

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!

标签: python timer
11条回答
走好不送
2楼-- · 2020-02-16 08:59

I was playing around with timing in Python 3.7 today and trying to pass functions and variables into the timer. This is what I came up with.

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} \n{func(text)}\n")

This outputs:

regex: 1.378352418
This is a test of the emergency broadcast system

loop_while: 0.15858950299999997
This is a test of the emergency broadcast system

Then all it takes to test a new version is adding in a new function. Something like:

def split_join(text):
    return " ".join(text.split())

Now it outputs:

regex: 1.378352418
This is a test of the emergency broadcast system

loop_while: 0.15858950299999997
This is a test of the emergency broadcast system

split_join: 0.05700970800000005
This is a test of the emergency broadcast system

查看更多
相关推荐>>
3楼-- · 2020-02-16 09:01

The code snippets must be self-contained - they cannot make external references. You must define your values in the statement-string or 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.

查看更多
家丑人穷心不美
4楼-- · 2020-02-16 09:02

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:

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
查看更多
ゆ 、 Hurt°
5楼-- · 2020-02-16 09:02

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

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.

查看更多
甜甜的少女心
6楼-- · 2020-02-16 09:04

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 = """
 # 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.

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

%prun foo("foo", 100)
查看更多
Evening l夕情丶
7楼-- · 2020-02-16 09:06

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))
查看更多
登录 后发表回答