I am having a hard time wrapping my head around
why i can make timeit.Timer()
work with output from
functools.partial()
but not with output from itertools.starmap()
.
What I basically need is starmap(func, tuples)
to have the same 'attributes' as partial(func, one_arg_only)
but be more generally in the sense that I can actually pass into func multiple arguments at the same time.
What's the easiest workaround here ?
I tried timeit.Timer(starmap(func,tuples))
and obviously get the notorious error:
ValueError: stmt is neither a string nor callable
I presume this is coz starmap's output is not callable. But how do I work around this ?
The itertools.starmap()
function returns an itertools.starmap
iterable type whereas functools.partial()
returns a functools.partial
callable type. timeit.Timer()
expects the first argument to be a callable
(or a string it can exec()
).
>>> type(itertools.starmap(lambda *args: list(args), [(1, 2)])
itertools.starmap
>>> type(functools.partial(lambda x: x+1, 1))
functools.partial
What you want to do is create a callable that will exhaust the iterable returned by itertools.starmap
. One way to do this would be to call the list()
function on the output of the starmap:
# This is the function to call
>>> example_func = lambda *args: len(args)
# This is the iterable that can call the example_func
>>> func_callers = itertools.starmap(example_func, [(1, 2)])
# This is the callable that actually processes func_callers
>>> execute_callers = lambda: list(func_callers)
# And finally using the timer
>>> timeit.Timer(execute_callers)