[issue1397474] timeit execution enviroment
rurpy the second <rurpy@yahoo.com> added the comment: I find the changes suggested by T Reedy and refined in the patch by E Bendersky an improvement. However, I found the following things confused me when reading it: "...constructor creates a function..." the constructor creates a Timeit instance, not a function. There is a method on that instance that is the function but the way it is phrased in like describing the autos coming off a Ford production line as "steering wheels". As written, the statement creates an immediate WTF reaction in my mind. "...that executes the *setup* statement..." Use of term "statement" here is confusing as that term already has a well defined meaning in Python docs. One can't syntactically use a statement as a function argument. Only by suspending this confusion and reading further does one discover that "statement" here means a string containing text of some python code or a callable object. Use of "statement" (singular) also directly conflicts with following information that states multiple statements are ok. Since the synopsis line already refers to "snippets", I think continuing to use that is better (having no preexisting conflicting meanings) than "statement". "...default to ``'pass'`..." The call summary immediately above makes clear what the default parameter values are. While fine to repeat it in text, it is not high priority information so should be moved to later in the description. "...or newlines as long as they don’t contain multi-line string literals..." What is a multi-line string literal? The Language Reference -> Lexical Analysis -> String Literals section says nothing about "multi-line literals". Is it "a\nb"? Or """a b"""? Both? '"a\nb"' actually works. '"""a b"""' doesn't of course but it is it is also clearly not valid python string syntax so I'm not sure that 'multi-line strings need even be mentioned. If it is mentioned then it should be made clear that multi-line string literals are not allowed not because timeit doesn't like them, but because python syntax allows no way to embed them in another string. . "...pre-defined user objects..." What does "pre-defined" mean? Builtin? Imported from stdlib? I would use a more explicit description here. I also think a short explanation of *why* one needs to import program objects in 'setup' makes it a little easier and quicker to understand what one is doing with the import, particularly if one is using timeit somewhere other than __main__.. Thus I suggest expanding that section slightly. Here is my attempt to adjust taking the above observations into account. (Sorry, can't supply a patch since I have slow internet connection and don't have source. Text below is just my hand edit of the "+" lines in Eli's patch.) Class for timing execution speed of small code snippets. A Timeit instance will contain a function (see :meth:`Timer.timeit`) that executes a snippet of "setup" code once and then times some number of executions of "stmt" code . The code snippets, given as arguments *setup* and *stmt* when creating the instance, may be either strings or callable objects. If a string, it may contain a python expression, statement, or multiple statements separated by ";" or newlines. Whitespace adhering to the usual Python indentation rules must follow any newlines. If a callable object, (often a function), the object is called with no arguments. Note that the timing overhead is a little larger in this case because of the extra function calls required. The *setup* and *stmt* parameters default to ``'pass'``. The *timer* parameter defaults to a platform-dependent timer function (see the module doc string). When the *setup* and *stmt* are run, they are run in a different namespace than that of the code that calls timeit(). To give *stmt* (whether it is a callable name or code string) access to objects defined in the code that calls timeit, *setup* can import any needed objects. For example, if your code defines function testfunc(), *setup* can contain, ``from __main__ import testfunc``, and code in *stmt* can then call testfunc. To measure the execution time of *stmt*, use the :meth:`Timer.timeit()` method. The :meth:`Timer.repeat()` method is a convenience to call :meth:`Timer.timeit()` multiple times and return a list of results. Changed in version 2.6: The stmt and setup parameters can now also take objects. Notes: ---- Added the line "Whitespace adhering..." because when using backslash-n in strings it is easy to forget about any needed indentation. Sentence could be deleted if deemed too obvious. There may also be a better way to phrase it; currently it might imply that some whitespace is always neccessary if not enough attention paid to the "usual indentation rules" phrase. ---- In msg116330 - Eli Bendersky (eli.bendersky) wrote:
1) My tests show that passing the callable instead of the string 'test()' actually takes longer to run.
Should the documentation promise that? I take your word that it also takes longer than running the function's code directly (outside a function) The original "Changed in version 2.6" section said | Note that the timing overhead is a little larger in this case | [callable objects] because of the extra function calls. Here, "the other case" is presumably the plain code but could also be a string function call (e.g. "test()") so I suppose it is still vacuously true in that case. Accordingly I reused the statement above in in my suggested changes. Perhaps all three cases (string code, string function call, callable object) should be distinguished further and compared re overhead? ---------- nosy: +rurpy2 _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue1397474> _______________________________________
participants (1)
-
rurpy the second