uTools-Manuals/docs/python/timeit.html
2019-04-21 11:50:48 +08:00

87 lines
35 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">timeit</span>
<span class="gp">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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=&lt;default timer&gt;</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=&lt;default timer&gt;</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=&lt;timer function&gt;</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">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">timeit</span>
<span class="gp">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">timeit</span>
<span class="gp">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">timeit</span>
<span class="gp">&gt;&gt;&gt; </span><span class="c1"># attribute is missing</span>
<span class="gp">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </span><span class="n">s</span> <span class="o">=</span> <span class="s2">"if hasattr(str, '__bool__'): pass"</span>
<span class="gp">&gt;&gt;&gt; </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">&gt;&gt;&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="c1"># attribute is present</span>
<span class="gp">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </span><span class="n">s</span> <span class="o">=</span> <span class="s2">"if hasattr(int, '__bool__'): pass"</span>
<span class="gp">&gt;&gt;&gt; </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>