-1

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 ?

DarK_FirefoX
  • 887
  • 8
  • 20
RWS
  • 1
  • 1
  • Could you please provide a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) and show what is exactly what you tried. – DarK_FirefoX Mar 31 '20 at 16:54

1 Answers1

1

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)
damon
  • 14,485
  • 14
  • 56
  • 75