I'd like some feedback on this li'l thing. If you want to have a look, the source is here, but I'm more interested in help on the API and naming stuff, so don't worry about that unless you want to!
I've written a wrapper for timeit.Timer
. It behaves a lot like the command line python -m timeit ...
interface, but makes comparison easier by providing a Python API for specifying functions to compare and arguments to use.
python -m timeit -s 'import my_function' 'my_function(10)'
You specify 10
as the arguments to the function and decorate my_function
with the provided decorator. When you run the comparisons, it prints a little table showing the results.
This makes comparisons more fun, if you ask me. Consider primeexample.py
and the resulting table, primeexample.txt
. If you called all those calls form the command line, you'd have to run
$ python -m timeit -s 'from example import check_all' 'check_all(10)'
...
$ python -m timeit -s 'from example import memozied' 'memoized(10)'
...
$ python -m timeit -s 'from example import sieve' 'sieve(10)'
...
$ python -m timeit -s 'from example import check_all' 'check_all(100)'
...
And so forth, and then collate all the results from the runs. This may be a strawman, exaggerated version of how hard and unpleasent it is, but I posit that the CLI requires lots of repetition for this use case, and the Timer
Python interface is more complicated than necessary (see here for examples of both). There should be a simpler interface for this.
classexample.py
and .txt
show the use of the class interface for specifying timings, and demonstrates that they classes can be used independently. primeexample.py
shows use of the module-level API, which (I think) makes casual use easier by avoiding setup. (Just so you know, the calls are just aliases for an already-instantiated SimpleTimeIt
object.) multiargs.py
demonstrates registering arguments for multi-argument functions, and its output is in multiargs.txt
. withsetup.py
and .txt
show how to use the _setup
parameter to do pre-timing setup.
So, while things aren't set in stone, I was hoping that y'all could give me some feedback on this thing!
- Is there anything I can do to make it more understandable? More Pythonic? More fun?
- Would you prefer any alternate interfaces for specifying arguments or functions?
- What kinds of timing, running, or printing configuration options would you use if provided?
- Is the provided module-level API a good idea? In principle I try to avoid giving modules state when possible, but since this is for scripts that fire off and finish quickly, I don't think there's a huge chance for silent/mysterious error when people don't anticipate the state hanging around.
And of course, most of all,
- Would you actually use this? When, and for what?
And of course, the worst but best part of this feedback request: what should things be named?
Since this is kind of a Pokémon-style battle between your functions, I've been thinking thought a synonym for 'battle' would be appropriate name for the module and its primary object. Under consideration:
- dustup
- fracas
- rhubarb (which is apparently a synonym for scuffle!)
- rumble
- scuffle
Rumble, as in "Let's Get Ready to Rumble!", is my current favorite. And I think a fun name for the function-registering decorator would be contender
, so
from rumble import Rumble
rumble = Rumble()
@rumble.contender
def memoized(n):
...
I am not super-attached to this "battle" idea, so other suggestions are welcome no matter how far afield!
I don't really like call_with
as the name for the other function, but I don't know what else to call it. Maybe just arguments
?