Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Local variables in Python timeit setup [duplicate]

In all of the places I read about timeit I found only that I can use variables in this way:

s1 = 'abc'
s2 = 'abc'
timeit.timeit('s1==s2', 'from __main__ import s1, s2', number=10**4)

or

s1 = 'abc'
s2 = 'abc'
def func():
    timeit.time('s1==s2', 'from __main__ import s1,s2', number=10**4)

which means that you can also use timeit.timeit in a function as long as the variables are in the main program. I would like to use timeit.timeit with variables that are within the scope it is in, for example:

def func():
    s1 = 'abc'
    s2 = 'abc'
    timeit.timeit(...)

As you can see my question is:

How can I use timeit.timeit with the variables that are in the same scope, when they're both not in the main program?

like image 460
pystudent Avatar asked Jul 22 '15 14:07

pystudent


People also ask

What is Timeit repeat?

Module Contents The timeit() method runs the setup statement one time, then executes the primary statement repeatedly and returns the amount of time that passes. The argument to timeit() controls how many times to run the statement; the default is 1,000,000.

What is the Timeit function in Python?

Source code: Lib/timeit.py. This module provides a simple way to time small bits of Python code. It has both a Command-Line Interface as well as a callable one. It avoids a number of common traps for measuring execution times.

Does Timeit return seconds?

The Python timeit() method accepts the code as a string and returns the execution time in seconds. On the contrary, the default_timer() method returns the time of its execution. The repeat() method calls the timeit() method a number of specified times.


1 Answers

I would like to use timeit.timeit with variables that are within the scope it is in.

TLDR:

Use a lambda closure (so called because it closes over the variables in the function):

def func():
    s1 = 'abc'
    s2 = 'abc'
    return timeit.timeit(lambda: s1 == s2)

And I think that's just about what you're asking for.

>>> func()
0.12512516975402832

Explanation

So in the global scope, you want to use the globals, and local scope, locals? On the global scope, locals() returns the same as globals(), so it you ', '.join(locals()) and stick that on the end of 'from __main__ import ', or globals() as they're equivalent on the global scope:

>>> s1 = 'abc'
>>> s2 = 'abc'
>>> timeit.timeit('s1==s2', 'from __main__ import ' + ', '.join(globals()))
0.14271061390928885

You could do this with a function and the globals() too, but you can't use locals():

s1 = 'abc'
s2 = 'abc'
def func():
    return timeit.timeit('s1==s2', 'from __main__ import ' + ', '.join(globals()))

and

>>> func()
0.14236921612231157

but the below doesn't work, because you've got to have access to the variables hidden in the local scope of the function, from the import statement:

def func():
    s1 = 'abc'
    s2 = 'abc'
    return timeit.timeit('s1==s2', 'from __main__ import ' + ', '.join(locals()))

But because you can simply pass the function to timeit, what you can do is this:

def func(s1='abc', s2='abc'):
    s1 == s2

and

>>> timeit.timeit(func)
0.14399981498718262

So that also means, in your func, you can provide timeit a lambda closure:

def func():
    s1 = 'abc'
    s2 = 'abc'
    return timeit.timeit(lambda: s1 == s2)

Or a full function def:

def func():
    s1 = 'abc'
    s2 = 'abc'
    def closure():
        return s1 == s2
    return timeit.timeit(closure)

And I think that's just about what you're asking for.

>>> func()
0.12512516975402832

When they're both not in the main program

If you want to join the globals instead with a setup, from other modules than __main__, use this:

'from ' + __name__ + ' import ' + ', '.join(globals())
like image 144
Russia Must Remove Putin Avatar answered Oct 15 '22 20:10

Russia Must Remove Putin