Passing function objects to timeit

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Sun Mar 30 04:23:07 CEST 2008


On Sat, 29 Mar 2008 21:12:33 -0300, Gabriel Genellina wrote:

> En Sat, 29 Mar 2008 07:33:40 -0300, Steven D'Aprano
> <steve at REMOVE-THIS-cybersource.com.au> escribió:
> 
>> The timeit.Timer class times "code snippets" -- you pass it strings
>> rather than function objects. That's good for what it's worth, but
>> sometimes the code you want to time is too big to easily pass as a
>> string, or maybe you only have access to a function object without the
>> source, or for whatever reason it's not very convenient.
>>
>> In this case, a good trick is to import the function by name:
>>
>> timeit.Timer('spam()', 'from __main__ import spam')
>>
>>
>> But now I find myself wanting to time a function that's not defined in
>> __main__. Here's a illustrative example:
>>
>>
>> def factory():
>>     def f():
>>         return "spam"
>>     return f
>>
>> def main():
>>     func = factory()
>>     return timeit.Timer('func()', 'from __main__ import func').timeit()
> 
> Would this help (untested)?
> 
> def main():
>    return timeit.Timer('func()', 'from __main__ import factory; func =
> factory()').timeit()


Unfortunately no.

The above was just a simple illustration. Perhaps I misled you by showing 
where func() came from, but what I intended to illustrate was that func() 
could come from *anywhere*. I might not know where it came from: all I 
have is a function object.

In fact, my question is actually more general than that, because my 
example was a little unrealistic in that the function took no arguments. 
I have to deal with the function arguments as well.

The general problem is that I wish to time an arbitrary function with 
arbitrary arguments. The function and arguments are provided to me as 
Python objects, but timeit requires strings. Converting the objects to 
strings is not practical, and the objects might not exist in the __main__ 
module.

The problem is that timeit creates its own namespace to execute the code 
in (which is a good thing!). Is there a way to insert arbitrary objects 
into that namespace?


> Or maybe:
> 
> def main():
>    global func
>    func = factory()
>    return timeit.Timer('func()', 'from __main__ import func').timeit()

I'll try playing around with that and see.


-- 
Steven



More information about the Python-list mailing list