mirror of
https://github.com/fofolee/uTools-Manuals.git
synced 2025-06-08 23:14:06 +08:00
87 lines
35 KiB
HTML
87 lines
35 KiB
HTML
<div class="body" role="main"><div class="section" id="module-timeit"><h1><span class="yiyi-st" id="yiyi-10">27.5. <a class="reference internal" href="#module-timeit" title="timeit: Measure the execution time of small code snippets."><code class="xref py py-mod docutils literal"><span class="pre">timeit</span></code></a> - 测量小代码片段的执行时间</span></h1><p><span class="yiyi-st" id="yiyi-11"><strong>源代码:</strong> <a class="reference external" href="https://hg.python.org/cpython/file/3.5/Lib/timeit.py">Lib / timeit.py</a></span></p><p><span class="yiyi-st" id="yiyi-12">本模块提供一个简单的方法来测量小的Python代码的时间。</span><span class="yiyi-st" id="yiyi-13">它同时具有<a class="reference internal" href="#timeit-command-line-interface"><span>Command-Line Interface</span></a>以及<a class="reference internal" href="#python-interface"><span>callable</span></a>的函数。</span><span class="yiyi-st" id="yiyi-14">它避免了测量执行时间时大量的常见陷阱。</span><span class="yiyi-st" id="yiyi-15">另请参阅O'Reilly出版的<em>Python Cookbook</em>一书中,由Tim Peters编写的"算法"简介一章。</span></p><div class="section" id="basic-examples"><h2><span class="yiyi-st" id="yiyi-16">27.5.1. </span><span class="yiyi-st" id="yiyi-17">Basic Examples</span></h2><p><span class="yiyi-st" id="yiyi-18">下面的示例演示如何使用<a class="reference internal" href="#timeit-command-line-interface"><span>Command-Line Interface</span></a>比较三种不同的表达式:</span></p><div class="highlight-sh"><div class="highlight"><pre><span></span>$ python3 -m timeit <span class="s1">'"-".join(str(n) for n in range(100))'</span>
|
||
<span class="m">10000</span> loops, best of 3: 30.2 usec per loop
|
||
$ python3 -m timeit <span class="s1">'"-".join([str(n) for n in range(100)])'</span>
|
||
<span class="m">10000</span> loops, best of 3: 27.5 usec per loop
|
||
$ python3 -m timeit <span class="s1">'"-".join(map(str, range(100)))'</span>
|
||
<span class="m">10000</span> loops, best of 3: 23.2 usec per loop
|
||
</pre></div></div><p><span class="yiyi-st" id="yiyi-19">这也可以通过<a class="reference internal" href="#python-interface"><span>Python Interface</span></a>实现:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">timeit</span>
|
||
<span class="gp">>>> </span><span class="n">timeit</span><span class="o">.</span><span class="n">timeit</span><span class="p">(</span><span class="s1">'"-".join(str(n) for n in range(100))'</span><span class="p">,</span> <span class="n">number</span><span class="o">=</span><span class="mi">10000</span><span class="p">)</span>
|
||
<span class="go">0.3018611848820001</span>
|
||
<span class="gp">>>> </span><span class="n">timeit</span><span class="o">.</span><span class="n">timeit</span><span class="p">(</span><span class="s1">'"-".join([str(n) for n in range(100)])'</span><span class="p">,</span> <span class="n">number</span><span class="o">=</span><span class="mi">10000</span><span class="p">)</span>
|
||
<span class="go">0.2727368790656328</span>
|
||
<span class="gp">>>> </span><span class="n">timeit</span><span class="o">.</span><span class="n">timeit</span><span class="p">(</span><span class="s1">'"-".join(map(str, range(100)))'</span><span class="p">,</span> <span class="n">number</span><span class="o">=</span><span class="mi">10000</span><span class="p">)</span>
|
||
<span class="go">0.23702679807320237</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-20">请注意,只有使用命令行接口时,<a class="reference internal" href="#module-timeit" title="timeit: Measure the execution time of small code snippets."><code class="xref py py-mod docutils literal"><span class="pre">timeit</span></code></a>才会自动确定循环的次数。</span><span class="yiyi-st" id="yiyi-21"><a class="reference internal" href="#timeit-examples"><span>Examples</span></a>一节中可以找到更高级的例子。</span></p></div><div class="section" id="python-interface"><h2><span class="yiyi-st" id="yiyi-22">27.5.2. </span><span class="yiyi-st" id="yiyi-23">Python Interface</span></h2><p><span class="yiyi-st" id="yiyi-24">该模块定义了三个便利的函数和用一个公共类:</span></p><dl class="function"><dt id="timeit.timeit"><span class="yiyi-st" id="yiyi-25"> <code class="descclassname">timeit.</code><code class="descname">timeit</code><span class="sig-paren">(</span><em>stmt='pass'</em>, <em>setup='pass'</em>, <em>timer=<default timer></em>, <em>number=1000000</em>, <em>globals=None</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-26">用给定的statement,<em>setup</em>代码和<em>timer</em>函数创建一个<a class="reference internal" href="#timeit.Timer" title="timeit.Timer"><code class="xref py py-class docutils literal"><span class="pre">Timer</span></code></a>实例,然后运行它的<a class="reference internal" href="#timeit.Timer.timeit" title="timeit.Timer.timeit"><code class="xref py py-meth docutils literal"><span class="pre">timeit()</span></code></a>方法执行<em>number</em>指定的次数。</span><span class="yiyi-st" id="yiyi-27">可选的<em>全局变量</em>参数指定在其中执行代码的命名空间。</span></p><div class="versionchanged"><p><span class="yiyi-st" id="yiyi-28"><span class="versionmodified">在版本3.5中已更改:</span>添加了可选的<em>全局</em>参数。</span></p></div></dd></dl><dl class="function"><dt id="timeit.repeat"><span class="yiyi-st" id="yiyi-29"> <code class="descclassname">timeit.</code><code class="descname">repeat</code><span class="sig-paren">(</span><em>stmt='pass'</em>, <em>setup='pass'</em>, <em>timer=<default timer></em>, <em>repeat=3</em>, <em>number=1000000</em>, <em>globals=None</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-30">用给定的statement,<em>setup</em>代码和<em>timer</em>函数创建一个<a class="reference internal" href="#timeit.Timer" title="timeit.Timer"><code class="xref py py-class docutils literal"><span class="pre">Timer</span></code></a>实例,并循环运行<a class="reference internal" href="#timeit.Timer.repeat" title="timeit.Timer.repeat"><code class="xref py py-meth docutils literal"><span class="pre">repeat()</span></code></a>方法直到<em>repeat</em>指定的计数,每次计数中代码运行<em>number</em>指定的执行次数。</span><span class="yiyi-st" id="yiyi-31">可选的<em>全局变量</em>参数指定在其中执行代码的命名空间。</span></p><div class="versionchanged"><p><span class="yiyi-st" id="yiyi-32"><span class="versionmodified">在版本3.5中已更改:</span>添加了可选的<em>全局</em>参数。</span></p></div></dd></dl><dl class="function"><dt id="timeit.default_timer"><span class="yiyi-st" id="yiyi-33"> <code class="descclassname">timeit.</code><code class="descname">default_timer</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-34">默认计时器,始终为<a class="reference internal" href="time.html#time.perf_counter" title="time.perf_counter"><code class="xref py py-func docutils literal"><span class="pre">time.perf_counter()</span></code></a>。</span></p><div class="versionchanged"><p><span class="yiyi-st" id="yiyi-35"><span class="versionmodified">在版本3.3中更改:</span> <a class="reference internal" href="time.html#time.perf_counter" title="time.perf_counter"><code class="xref py py-func docutils literal"><span class="pre">time.perf_counter()</span></code></a>现在是默认计时器。</span></p></div></dd></dl><dl class="class"><dt id="timeit.Timer"><span class="yiyi-st" id="yiyi-36"> <em class="property">class </em><code class="descclassname">timeit.</code><code class="descname">Timer</code><span class="sig-paren">(</span><em>stmt='pass'</em>, <em>setup='pass'</em>, <em>timer=<timer function></em>, <em>globals=None</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-37">用于计时小代码段执行速度的类。</span></p><p><span class="yiyi-st" id="yiyi-38">该构造函数接受要计时的语句,以及一个额外的用于初始化的语句和一个计时器函数。</span><span class="yiyi-st" id="yiyi-39">两个语句默认为<code class="docutils literal"><span class="pre">'pass'</span></code>;定时器功能是平台相关的(参见模块doc字符串)。</span><span class="yiyi-st" id="yiyi-40"><em>stmt</em>和<em>设置</em>也可能包含多个由<code class="docutils literal"><span class="pre">;</span></code>分隔的语句或换行符,只要它们不包含多行字符串字面值即可。</span><span class="yiyi-st" id="yiyi-41">语句将默认在timeit的命名空间中执行;可以通过将命名空间传递到<em>全局变量</em>来控制此行为。</span></p><p><span class="yiyi-st" id="yiyi-42">若要测量的第一个语句的执行时间,请使用<a class="reference internal" href="#timeit.Timer.timeit" title="timeit.Timer.timeit"><code class="xref py py-meth docutils literal"><span class="pre">timeit()</span></code></a>方法。</span><span class="yiyi-st" id="yiyi-43"><a class="reference internal" href="#timeit.Timer.repeat" title="timeit.Timer.repeat"><code class="xref py py-meth docutils literal"><span class="pre">repeat()</span></code></a>方法是多次调用<a class="reference internal" href="#timeit.Timer.timeit" title="timeit.Timer.timeit"><code class="xref py py-meth docutils literal"><span class="pre">timeit()</span></code></a>的一种便利方法,并返回结果的列表。</span></p><p><span class="yiyi-st" id="yiyi-44"><em>设置</em>的执行时间从整个定时执行运行中排除。</span></p><p><span class="yiyi-st" id="yiyi-45"><em>stmt</em>和<em>设置</em>参数也可以使用无参数可调用的对象。</span><span class="yiyi-st" id="yiyi-46">这将在随后由<a class="reference internal" href="#timeit.Timer.timeit" title="timeit.Timer.timeit"><code class="xref py py-meth docutils literal"><span class="pre">timeit()</span></code></a>执行的定时器函数中嵌入对它们的调用。</span><span class="yiyi-st" id="yiyi-47">请注意在这种情况下由于额外的函数调用时间开销会有点大。</span></p><div class="versionchanged"><p><span class="yiyi-st" id="yiyi-48"><span class="versionmodified">在版本3.5中已更改:</span>添加了可选的<em>全局</em>参数。</span></p></div><dl class="method"><dt id="timeit.Timer.timeit"><span class="yiyi-st" id="yiyi-49"> <code class="descname">timeit</code><span class="sig-paren">(</span><em>number=1000000</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-50">计时主要语句执行<em>number</em>次的时间。</span><span class="yiyi-st" id="yiyi-51">它将执行一次setup语句,返回执行主要语句执行多次所需的时间,以浮点数秒数表示。</span><span class="yiyi-st" id="yiyi-52">参数为循环的次数,默认是100万。</span><span class="yiyi-st" id="yiyi-53">要用的主语句、setup语句和计时器函数将传递给构造函数。</span></p><div class="admonition note"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-54">注</span></p><p><span class="yiyi-st" id="yiyi-55">默认情况下,在计时期间<a class="reference internal" href="#timeit.Timer.timeit" title="timeit.Timer.timeit"><code class="xref py py-meth docutils literal"><span class="pre">timeit()</span></code></a>暂时关闭<a class="reference internal" href="../glossary.html#term-garbage-collection"><span class="xref std std-term">garbage collection</span></a>。</span><span class="yiyi-st" id="yiyi-56">这种方法的优点是它使得独立的计时更具有可比性。</span><span class="yiyi-st" id="yiyi-57">缺点是垃圾回收可能被测量函数性能的一个重要组成部分。</span><span class="yiyi-st" id="yiyi-58">如果是这样,垃圾回收可以利用<em>setup</em>字符串的第一个语句重新启用。</span><span class="yiyi-st" id="yiyi-59">举个例子:</span></p><div class="last highlight-python3"><div class="highlight"><pre><span></span><span class="n">timeit</span><span class="o">.</span><span class="n">Timer</span><span class="p">(</span><span class="s1">'for i in range(10): oct(i)'</span><span class="p">,</span> <span class="s1">'gc.enable()'</span><span class="p">)</span><span class="o">.</span><span class="n">timeit</span><span class="p">()</span>
|
||
</pre></div></div></div></dd></dl><dl class="method"><dt id="timeit.Timer.repeat"><span class="yiyi-st" id="yiyi-60"> <code class="descname">repeat</code><span class="sig-paren">(</span><em>repeat=3</em>, <em>number=1000000</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-61">调用<a class="reference internal" href="#timeit.Timer.timeit" title="timeit.Timer.timeit"><code class="xref py py-meth docutils literal"><span class="pre">timeit()</span></code></a>多次。</span></p><p><span class="yiyi-st" id="yiyi-62">这是一个方便的函数重复调用<a class="reference internal" href="#timeit.Timer.timeit" title="timeit.Timer.timeit"><code class="xref py py-meth docutils literal"><span class="pre">timeit()</span></code></a>,并返回结果的列表。</span><span class="yiyi-st" id="yiyi-63">第一个参数指定调用<a class="reference internal" href="#timeit.Timer.timeit" title="timeit.Timer.timeit"><code class="xref py py-meth docutils literal"><span class="pre">timeit()</span></code></a>多少次。</span><span class="yiyi-st" id="yiyi-64">第二个参数指定<a class="reference internal" href="#timeit.Timer.timeit" title="timeit.Timer.timeit"><code class="xref py py-meth docutils literal"><span class="pre">timeit()</span></code></a>的<em>number</em>参数。</span></p><div class="admonition note"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-65">注</span></p><p class="last"><span class="yiyi-st" id="yiyi-66">从结果向量它很容易计算平均值和标准偏差,并报告这些。</span><span class="yiyi-st" id="yiyi-67">然而,这不是很有用的。</span><span class="yiyi-st" id="yiyi-68">在典型情况下,最低值给出了您的机器运行给定代码片段的速度的下限;结果向量中较高的值通常不是由Python的速度变化引起的,而是由其他进程干扰您的时序精度造成的。</span><span class="yiyi-st" id="yiyi-69">所以结果中的<a class="reference internal" href="functions.html#min" title="min"><code class="xref py py-func docutils literal"><span class="pre">min()</span></code></a>可能你应该感兴趣的唯一一个数。</span><span class="yiyi-st" id="yiyi-70">在那之后,你应该看看整个矢量并应用常识而不是统计数据。</span></p></div></dd></dl><dl class="method"><dt id="timeit.Timer.print_exc"><span class="yiyi-st" id="yiyi-71"> <code class="descname">print_exc</code><span class="sig-paren">(</span><em>file=None</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-72">从被计时的代码打印回溯的helper。</span></p><p><span class="yiyi-st" id="yiyi-73">典型的使用:</span></p><pre><code class="language-python"><span></span><span class="n">t</span> <span class="o">=</span> <span class="n">Timer</span><span class="p">(</span><span class="o">...</span><span class="p">)</span> <span class="c1"># outside the try/except</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="n">t</span><span class="o">.</span><span class="n">timeit</span><span class="p">(</span><span class="o">...</span><span class="p">)</span> <span class="c1"># or t.repeat(...)</span>
|
||
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
|
||
<span class="n">t</span><span class="o">.</span><span class="n">print_exc</span><span class="p">()</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-74">相比标准的回溯的优点是将显示编译后的模板中的源代码行。</span><span class="yiyi-st" id="yiyi-75">可选的<em>文件</em>参数指示发送回溯的位置;它默认为<a class="reference internal" href="sys.html#sys.stderr" title="sys.stderr"><code class="xref py py-data docutils literal"><span class="pre">sys.stderr</span></code></a>。</span></p></dd></dl></dd></dl></div><div class="section" id="command-line-interface"><h2><span class="yiyi-st" id="yiyi-76">27.5.3. </span><span class="yiyi-st" id="yiyi-77">Command-Line Interface</span></h2><p><span class="yiyi-st" id="yiyi-78">当作为一个程序从命令行调用时,使用以下格式:</span></p><pre><code class="language-python"><span></span><span class="n">python</span> <span class="o">-</span><span class="n">m</span> <span class="n">timeit</span> <span class="p">[</span><span class="o">-</span><span class="n">n</span> <span class="n">N</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="n">r</span> <span class="n">N</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="n">u</span> <span class="n">U</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="n">s</span> <span class="n">S</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="n">t</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="n">c</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="n">h</span><span class="p">]</span> <span class="p">[</span><span class="n">statement</span> <span class="o">...</span><span class="p">]</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-79">下面是选项的解释:</span></p><dl class="cmdoption"><dt id="cmdoption-timeit-n"><span class="yiyi-st" id="yiyi-80"> <span id="cmdoption-timeit--number"></span><code class="descname">-n</code><code class="descclassname"> N</code><code class="descclassname">, </code><code class="descname">--number</code><code class="descclassname">=N</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-81">执行'statement'多少次</span></p></dd></dl><dl class="cmdoption"><dt id="cmdoption-timeit-r"><span class="yiyi-st" id="yiyi-82"> <span id="cmdoption-timeit--repeat"></span><code class="descname">-r</code><code class="descclassname"> N</code><code class="descclassname">, </code><code class="descname">--repeat</code><code class="descclassname">=N</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-83">重复计时器多少次(默认为3)</span></p></dd></dl><dl class="cmdoption"><dt id="cmdoption-timeit-s"><span class="yiyi-st" id="yiyi-84"> <span id="cmdoption-timeit--setup"></span><code class="descname">-s</code><code class="descclassname"> S</code><code class="descclassname">, </code><code class="descname">--setup</code><code class="descclassname">=S</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-85">一旦初识化后要执行的语句(默认为<code class="docutils literal"><span class="pre">pass</span></code>)</span></p></dd></dl><dl class="cmdoption"><dt id="cmdoption-timeit-p"><span class="yiyi-st" id="yiyi-86"> <span id="cmdoption-timeit--process"></span><code class="descname">-p</code><code class="descclassname"></code><code class="descclassname">, </code><code class="descname">--process</code><code class="descclassname"></code></span></dt><dd><p><span class="yiyi-st" id="yiyi-87">测量处理时间,而不是时钟时间,使用<a class="reference internal" href="time.html#time.process_time" title="time.process_time"><code class="xref py py-func docutils literal"><span class="pre">time.process_time()</span></code></a>而不是<a class="reference internal" href="time.html#time.perf_counter" title="time.perf_counter"><code class="xref py py-func docutils literal"><span class="pre">time.perf_counter()</span></code></a></span></p><div class="versionadded"><p><span class="yiyi-st" id="yiyi-88"><span class="versionmodified">版本3.3中的新功能。</span></span></p></div></dd></dl><dl class="cmdoption"><dt id="cmdoption-timeit-t"><span class="yiyi-st" id="yiyi-89"> <span id="cmdoption-timeit--time"></span><code class="descname">-t</code><code class="descclassname"></code><code class="descclassname">, </code><code class="descname">--time</code><code class="descclassname"></code></span></dt><dd><p><span class="yiyi-st" id="yiyi-90">使用<a class="reference internal" href="time.html#time.time" title="time.time"><code class="xref py py-func docutils literal"><span class="pre">time.time()</span></code></a>(已弃用)</span></p></dd></dl><dl class="cmdoption"><dt id="cmdoption-timeit-u"><span class="yiyi-st" id="yiyi-91"> <span id="cmdoption-timeit--unit"></span><code class="descname">-u</code><code class="descclassname"></code><code class="descclassname">, </code><code class="descname">--unit</code><code class="descclassname">=U</code></span></dt><dd><span class="yiyi-st" id="yiyi-93"><blockquote> <div>specify a time unit for timer output; can select usec, msec, or sec</div></blockquote></span><div class="versionadded"><p><span class="yiyi-st" id="yiyi-92"><span class="versionmodified">版本3.5中的新功能。</span></span></p></div></dd></dl><dl class="cmdoption"><dt id="cmdoption-timeit-c"><span class="yiyi-st" id="yiyi-94"> <span id="cmdoption-timeit--clock"></span><code class="descname">-c</code><code class="descclassname"></code><code class="descclassname">, </code><code class="descname">--clock</code><code class="descclassname"></code></span></dt><dd><p><span class="yiyi-st" id="yiyi-95">使用<a class="reference internal" href="time.html#time.clock" title="time.clock"><code class="xref py py-func docutils literal"><span class="pre">time.clock()</span></code></a>(已弃用)</span></p></dd></dl><dl class="cmdoption"><dt id="cmdoption-timeit-v"><span class="yiyi-st" id="yiyi-96"> <span id="cmdoption-timeit--verbose"></span><code class="descname">-v</code><code class="descclassname"></code><code class="descclassname">, </code><code class="descname">--verbose</code><code class="descclassname"></code></span></dt><dd><p><span class="yiyi-st" id="yiyi-97">打印原始时序结果;重复以获得更多数字精度</span></p></dd></dl><dl class="cmdoption"><dt id="cmdoption-timeit-h"><span class="yiyi-st" id="yiyi-98"> <span id="cmdoption-timeit--help"></span><code class="descname">-h</code><code class="descclassname"></code><code class="descclassname">, </code><code class="descname">--help</code><code class="descclassname"></code></span></dt><dd><p><span class="yiyi-st" id="yiyi-99">打印一个短的用法信息并退出</span></p></dd></dl><p><span class="yiyi-st" id="yiyi-100">多行语句可以通过将每一行指定为单独的语句参数来给出;缩进线可以通过使用引号包围参数并使用前导空格。</span><span class="yiyi-st" id="yiyi-101">多个<a class="reference internal" href="#cmdoption-timeit-s"><code class="xref std std-option docutils literal"><span class="pre">-s</span></code></a>选项的处理方式类似。</span></p><p><span class="yiyi-st" id="yiyi-102">如果不指定<a class="reference internal" href="#cmdoption-timeit-n"><code class="xref std std-option docutils literal"><span class="pre">-n</span></code></a> ,适当数目的循环计算的尝试连续的 10 的幂,直到总的时间为至少 0.2 秒。</span></p><p><span class="yiyi-st" id="yiyi-103"><a class="reference internal" href="#timeit.default_timer" title="timeit.default_timer"><code class="xref py py-func docutils literal"><span class="pre">default_timer()</span></code></a>测量可能会受到在同一台机器上运行的其他程序的影响,因此,当需要准确计时时,最好的做法是重复计时几次,并使用最佳时间。</span><span class="yiyi-st" id="yiyi-104"><a class="reference internal" href="#cmdoption-timeit-r"><code class="xref std std-option docutils literal"><span class="pre">-r</span></code></a>选项对此有好处;在大多数情况下默认为3次重复可能就足够了。</span><span class="yiyi-st" id="yiyi-105">您可以使用<a class="reference internal" href="time.html#time.process_time" title="time.process_time"><code class="xref py py-func docutils literal"><span class="pre">time.process_time()</span></code></a>来测量CPU时间。</span></p><div class="admonition note"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-106">注</span></p><p class="last"><span class="yiyi-st" id="yiyi-107">还有与执行 pass 语句相关联的某些基线系统开销。</span><span class="yiyi-st" id="yiyi-108">这里的代码不会尝试隐藏它,但是你应该意识到这一点。</span><span class="yiyi-st" id="yiyi-109">可以通过调用不带参数,程序测量基线开销和 Python 版本之间可能有差异。</span></p></div></div><div class="section" id="examples"><h2><span class="yiyi-st" id="yiyi-110">27.5.4. </span><span class="yiyi-st" id="yiyi-111">Examples</span></h2><p><span class="yiyi-st" id="yiyi-112">可以提供在开始时只执行一次的setup语句:</span></p><div class="highlight-sh"><div class="highlight"><pre><span></span>$ python -m timeit -s <span class="s1">'text = "sample string"; char = "g"'</span> <span class="s1">'char in text'</span>
|
||
<span class="m">10000000</span> loops, best of 3: 0.0877 usec per loop
|
||
$ python -m timeit -s <span class="s1">'text = "sample string"; char = "g"'</span> <span class="s1">'text.find(char)'</span>
|
||
<span class="m">1000000</span> loops, best of 3: 0.342 usec per loop
|
||
</pre></div></div><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">timeit</span>
|
||
<span class="gp">>>> </span><span class="n">timeit</span><span class="o">.</span><span class="n">timeit</span><span class="p">(</span><span class="s1">'char in text'</span><span class="p">,</span> <span class="n">setup</span><span class="o">=</span><span class="s1">'text = "sample string"; char = "g"'</span><span class="p">)</span>
|
||
<span class="go">0.41440500499993504</span>
|
||
<span class="gp">>>> </span><span class="n">timeit</span><span class="o">.</span><span class="n">timeit</span><span class="p">(</span><span class="s1">'text.find(char)'</span><span class="p">,</span> <span class="n">setup</span><span class="o">=</span><span class="s1">'text = "sample string"; char = "g"'</span><span class="p">)</span>
|
||
<span class="go">1.7246671520006203</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-113">同样可以使用<a class="reference internal" href="#timeit.Timer" title="timeit.Timer"><code class="xref py py-class docutils literal"><span class="pre">Timer</span></code></a>类和它的方法做到:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">timeit</span>
|
||
<span class="gp">>>> </span><span class="n">t</span> <span class="o">=</span> <span class="n">timeit</span><span class="o">.</span><span class="n">Timer</span><span class="p">(</span><span class="s1">'char in text'</span><span class="p">,</span> <span class="n">setup</span><span class="o">=</span><span class="s1">'text = "sample string"; char = "g"'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">t</span><span class="o">.</span><span class="n">timeit</span><span class="p">()</span>
|
||
<span class="go">0.3955516149999312</span>
|
||
<span class="gp">>>> </span><span class="n">t</span><span class="o">.</span><span class="n">repeat</span><span class="p">()</span>
|
||
<span class="go">[0.40193588800002544, 0.3960157959998014, 0.39594301399984033]</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-114">下面的示例演示如何计时包含多行的表达式。</span><span class="yiyi-st" id="yiyi-115">在这里我们比较使用<a class="reference internal" href="functions.html#hasattr" title="hasattr"><code class="xref py py-func docutils literal"><span class="pre">hasattr()</span></code></a>与<a class="reference internal" href="../reference/compound_stmts.html#try"><code class="xref std std-keyword docutils literal"><span class="pre">try</span></code></a>/<a class="reference internal" href="../reference/compound_stmts.html#except"><code class="xref std std-keyword docutils literal"><span class="pre">except</span></code></a>来测试对象缺失和存在的属性:</span></p><div class="highlight-sh"><div class="highlight"><pre><span></span>$ python -m timeit <span class="s1">'try:'</span> <span class="s1">' str.__bool__'</span> <span class="s1">'except AttributeError:'</span> <span class="s1">' pass'</span>
|
||
<span class="m">100000</span> loops, best of 3: 15.7 usec per loop
|
||
$ python -m timeit <span class="s1">'if hasattr(str, "__bool__"): pass'</span>
|
||
<span class="m">100000</span> loops, best of 3: 4.26 usec per loop
|
||
|
||
$ python -m timeit <span class="s1">'try:'</span> <span class="s1">' int.__bool__'</span> <span class="s1">'except AttributeError:'</span> <span class="s1">' pass'</span>
|
||
<span class="m">1000000</span> loops, best of 3: 1.43 usec per loop
|
||
$ python -m timeit <span class="s1">'if hasattr(int, "__bool__"): pass'</span>
|
||
<span class="m">100000</span> loops, best of 3: 2.23 usec per loop
|
||
</pre></div></div><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">timeit</span>
|
||
<span class="gp">>>> </span><span class="c1"># attribute is missing</span>
|
||
<span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="s2">"""</span><span class="se">\</span>
|
||
<span class="gp">... </span><span class="s2">try:</span>
|
||
<span class="gp">... </span><span class="s2"> str.__bool__</span>
|
||
<span class="gp">... </span><span class="s2">except AttributeError:</span>
|
||
<span class="gp">... </span><span class="s2"> pass</span>
|
||
<span class="gp">... </span><span class="s2">"""</span>
|
||
<span class="gp">>>> </span><span class="n">timeit</span><span class="o">.</span><span class="n">timeit</span><span class="p">(</span><span class="n">stmt</span><span class="o">=</span><span class="n">s</span><span class="p">,</span> <span class="n">number</span><span class="o">=</span><span class="mi">100000</span><span class="p">)</span>
|
||
<span class="go">0.9138244460009446</span>
|
||
<span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="s2">"if hasattr(str, '__bool__'): pass"</span>
|
||
<span class="gp">>>> </span><span class="n">timeit</span><span class="o">.</span><span class="n">timeit</span><span class="p">(</span><span class="n">stmt</span><span class="o">=</span><span class="n">s</span><span class="p">,</span> <span class="n">number</span><span class="o">=</span><span class="mi">100000</span><span class="p">)</span>
|
||
<span class="go">0.5829014980008651</span>
|
||
<span class="go">>>></span>
|
||
<span class="gp">>>> </span><span class="c1"># attribute is present</span>
|
||
<span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="s2">"""</span><span class="se">\</span>
|
||
<span class="gp">... </span><span class="s2">try:</span>
|
||
<span class="gp">... </span><span class="s2"> int.__bool__</span>
|
||
<span class="gp">... </span><span class="s2">except AttributeError:</span>
|
||
<span class="gp">... </span><span class="s2"> pass</span>
|
||
<span class="gp">... </span><span class="s2">"""</span>
|
||
<span class="gp">>>> </span><span class="n">timeit</span><span class="o">.</span><span class="n">timeit</span><span class="p">(</span><span class="n">stmt</span><span class="o">=</span><span class="n">s</span><span class="p">,</span> <span class="n">number</span><span class="o">=</span><span class="mi">100000</span><span class="p">)</span>
|
||
<span class="go">0.04215312199994514</span>
|
||
<span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="s2">"if hasattr(int, '__bool__'): pass"</span>
|
||
<span class="gp">>>> </span><span class="n">timeit</span><span class="o">.</span><span class="n">timeit</span><span class="p">(</span><span class="n">stmt</span><span class="o">=</span><span class="n">s</span><span class="p">,</span> <span class="n">number</span><span class="o">=</span><span class="mi">100000</span><span class="p">)</span>
|
||
<span class="go">0.08588060699912603</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-116">为了给<a class="reference internal" href="#module-timeit" title="timeit: Measure the execution time of small code snippets."><code class="xref py py-mod docutils literal"><span class="pre">timeit</span></code></a>模块访问给您定义的函数的权限,可以通过传递<em>setup</em>参数,其中包含import语句:</span></p><pre><code class="language-python"><span></span><span class="k">def</span> <span class="nf">test</span><span class="p">():</span>
|
||
<span class="sd">"""Stupid test function"""</span>
|
||
<span class="n">L</span> <span class="o">=</span> <span class="p">[</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">100</span><span class="p">)]</span>
|
||
|
||
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
|
||
<span class="kn">import</span> <span class="nn">timeit</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">timeit</span><span class="o">.</span><span class="n">timeit</span><span class="p">(</span><span class="s2">"test()"</span><span class="p">,</span> <span class="n">setup</span><span class="o">=</span><span class="s2">"from __main__ import test"</span><span class="p">))</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-117">另一个选项是将<a class="reference internal" href="functions.html#globals" title="globals"><code class="xref py py-func docutils literal"><span class="pre">globals()</span></code></a>传递到<em>全局</em>参数,这将导致代码在当前全局命名空间中执行。</span><span class="yiyi-st" id="yiyi-118">这可以比单独指定导入更方便:</span></p><pre><code class="language-python"><span></span><span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="n">x</span><span class="o">**</span><span class="mi">2</span>
|
||
<span class="k">def</span> <span class="nf">g</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="n">x</span><span class="o">**</span><span class="mi">4</span>
|
||
<span class="k">def</span> <span class="nf">h</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="n">x</span><span class="o">**</span><span class="mi">8</span>
|
||
|
||
<span class="kn">import</span> <span class="nn">timeit</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">timeit</span><span class="o">.</span><span class="n">timeit</span><span class="p">(</span><span class="s1">'[func(42) for func in (f,g,h)]'</span><span class="p">,</span> <span class="nb">globals</span><span class="o">=</span><span class="nb">globals</span><span class="p">()))</span>
|
||
</code></pre></div></div></div> |