“Python/docs/3.9/library/timeit”的版本间差异

来自菜鸟教程
Python/docs/3.9/library/timeit
跳转至:导航、​搜索
(autoload)
 
(Page commit)
 
第1行: 第1行:
 +
{{DISPLAYTITLE:timeit — 测量小代码片段的执行时间 — Python 文档}}
 
<div id="module-timeit" class="section">
 
<div id="module-timeit" class="section">
  
 
<span id="timeit-measure-execution-time-of-small-code-snippets"></span>
 
<span id="timeit-measure-execution-time-of-small-code-snippets"></span>
= [[#module-timeit|<code>timeit</code>]] --- Measure execution time of small code snippets =
+
= timeit — 测量小代码片段的执行时间 =
  
'''Source code:''' [https://github.com/python/cpython/tree/3.9/Lib/timeit.py Lib/timeit.py]
+
'''源代码:''' [[#id1|<span id="id2" class="problematic">:source:`Lib/timeit.py`</span>]]
  
This module provides a simple way to time small bits of Python code. It has both
+
 
a [[#timeit-command-line-interface|<span class="std std-ref">Command-Line Interface</span>]] as well as a [[#python-interface|<span class="std std-ref">callable</span>]]
+
-----
one. It avoids a number of common traps for measuring execution times.
+
 
See also Tim Peters' introduction to the &quot;Algorithms&quot; chapter in the ''Python
+
该模块提供了一种简单的方法来计时一小段 Python 代码。 它既有 [[#timeit-command-line-interface|命令行接口]] ,也有 [[#python-interface|可调用]] 接口。 它避免了许多用于测量执行时间的常见陷阱。 另请参阅 O'Reilly 出版的 ''Python Cookbook'' 第二版中 Tim Peters 对“算法”章节的介绍。
Cookbook'', published by O'Reilly.
 
  
 
<div id="basic-examples" class="section">
 
<div id="basic-examples" class="section">
  
== Basic Examples ==
+
== 基本示例 ==
  
The following example shows how the [[#timeit-command-line-interface|<span class="std std-ref">Command-Line Interface</span>]]
+
以下示例显示了如何使用 [[#timeit-command-line-interface|命令行界面]] 来比较三种不同的表达式:
can be used to compare three different expressions:
 
  
 
<div class="highlight-shell-session notranslate">
 
<div class="highlight-shell-session notranslate">
第23行: 第22行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>$ python3 -m timeit '&quot;-&quot;.join(str(n) for n in range(100))'
+
<pre class="session">$ python3 -m timeit '&quot;-&quot;.join(str(n) for n in range(100))'
 
10000 loops, best of 5: 30.2 usec per loop
 
10000 loops, best of 5: 30.2 usec per loop
 
$ python3 -m timeit '&quot;-&quot;.join([str(n) for n in range(100)])'
 
$ python3 -m timeit '&quot;-&quot;.join([str(n) for n in range(100)])'
第33行: 第32行:
  
 
</div>
 
</div>
This can be achieved from the [[#python-interface|<span class="std std-ref">Python Interface</span>]] with:
+
这可以通过 [[#python-interface|Python 接口]] 实现:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第39行: 第38行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; import timeit
+
<syntaxhighlight lang="python3">>>> import timeit
&gt;&gt;&gt; timeit.timeit('&quot;-&quot;.join(str(n) for n in range(100))', number=10000)
+
>>> timeit.timeit('"-".join(str(n) for n in range(100))', number=10000)
 
0.3018611848820001
 
0.3018611848820001
&gt;&gt;&gt; timeit.timeit('&quot;-&quot;.join([str(n) for n in range(100)])', number=10000)
+
>>> timeit.timeit('"-".join([str(n) for n in range(100)])', number=10000)
 
0.2727368790656328
 
0.2727368790656328
&gt;&gt;&gt; timeit.timeit('&quot;-&quot;.join(map(str, range(100)))', number=10000)
+
>>> timeit.timeit('"-".join(map(str, range(100)))', number=10000)
0.23702679807320237</pre>
+
0.23702679807320237</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
A callable can also be passed from the [[#python-interface|<span class="std std-ref">Python Interface</span>]]:
+
也可以从 [[#python-interface|Python 接口]] 传递一个可调用对象:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第56行: 第55行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; timeit.timeit(lambda: &quot;-&quot;.join(map(str, range(100))), number=10000)
+
<syntaxhighlight lang="python3">>>> timeit.timeit(lambda: "-".join(map(str, range(100))), number=10000)
0.19665591977536678</pre>
+
0.19665591977536678</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Note however that [[#timeit.timeit|<code>timeit()</code>]] will automatically determine the number of
+
但是请注意,只有在使用命令行界面时, [[#timeit.timeit|timeit()]] 才会自动确定重复次数。 在 [[#timeit-examples|示例]] 部分,您可以找到更高级的示例。
repetitions only when the command-line interface is used. In the
 
[[#timeit-examples|<span class="std std-ref">Examples</span>]] section you can find more advanced examples.
 
  
  
第70行: 第67行:
 
<div id="python-interface" class="section">
 
<div id="python-interface" class="section">
  
<span id="id1"></span>
+
<span id="id3"></span>
== Python Interface ==
+
== Python接口 ==
  
The module defines three convenience functions and a public class:
+
该模块定义了三个便利函数和一个公共类:
  
 
<dl>
 
<dl>
<dt><code>timeit.</code><code>timeit</code><span class="sig-paren">(</span>''stmt='pass''', ''setup='pass''', ''timer=&lt;default timer&gt;'', ''number=1000000'', ''globals=None''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">timeit.</span></span><span class="sig-name descname"><span class="pre">timeit</span></span><span class="sig-paren">(</span>''<span class="pre">stmt='pass'</span>'', ''<span class="pre">setup='pass'</span>'', ''<span class="pre">timer=&lt;default</span> <span class="pre">timer&gt;</span>'', ''<span class="pre">number=1000000</span>'', ''<span class="pre">globals=None</span>''<span class="sig-paren">)</span></dt>
<dd><p>Create a [[#timeit.Timer|<code>Timer</code>]] instance with the given statement, ''setup'' code and
+
<dd><p>使用给定的语句、''setup'' 代码和 ''timer'' 函数创建一个 [[#timeit.Timer|Timer]] 实例,并使用 ''编号运行其 [[#timeit.Timer.timeit|timeit()]] 方法'' 处决。 可选的 ''globals'' 参数指定执行代码的命名空间。</p>
''timer'' function and run its [[#timeit.Timer.timeit|<code>timeit()</code>]] method with ''number'' executions.
 
The optional ''globals'' argument specifies a namespace in which to execute the
 
code.</p>
 
 
<div class="versionchanged">
 
<div class="versionchanged">
  
<p><span class="versionmodified changed">在 3.5 版更改: </span>The optional ''globals'' parameter was added.</p>
+
<p><span class="versionmodified changed"> 在 3.5 版更改: </span> 添加了可选的 ''globals'' 参数。</p>
  
 
</div></dd></dl>
 
</div></dd></dl>
  
 
<dl>
 
<dl>
<dt><code>timeit.</code><code>repeat</code><span class="sig-paren">(</span>''stmt='pass''', ''setup='pass''', ''timer=&lt;default timer&gt;'', ''repeat=5'', ''number=1000000'', ''globals=None''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">timeit.</span></span><span class="sig-name descname"><span class="pre">repeat</span></span><span class="sig-paren">(</span>''<span class="pre">stmt='pass'</span>'', ''<span class="pre">setup='pass'</span>'', ''<span class="pre">timer=&lt;default</span> <span class="pre">timer&gt;</span>'', ''<span class="pre">repeat=5</span>'', ''<span class="pre">number=1000000</span>'', ''<span class="pre">globals=None</span>''<span class="sig-paren">)</span></dt>
<dd><p>Create a [[#timeit.Timer|<code>Timer</code>]] instance with the given statement, ''setup'' code and
+
<dd><p>使用给定的语句、''setup'' 代码和 ''timer'' 函数创建一个 [[#timeit.Timer|Timer]] 实例,并使用给定的 ''运行其 [[#timeit.Timer.repeat|repeat()]] 方法]repeat'' 计数和 ''number'' 次执行。 可选的 ''globals'' 参数指定执行代码的命名空间。</p>
''timer'' function and run its [[#timeit.Timer.repeat|<code>repeat()</code>]] method with the given ''repeat''
 
count and ''number'' executions. The optional ''globals'' argument specifies a
 
namespace in which to execute the code.</p>
 
 
<div class="versionchanged">
 
<div class="versionchanged">
  
<p><span class="versionmodified changed">在 3.5 版更改: </span>The optional ''globals'' parameter was added.</p>
+
<p><span class="versionmodified changed"> 在 3.5 版更改: </span> 添加了可选的 ''globals'' 参数。</p>
  
 
</div>
 
</div>
 
<div class="versionchanged">
 
<div class="versionchanged">
  
<p><span class="versionmodified changed">3.7 版更改: </span>Default value of ''repeat'' changed from 3 to 5.</p>
+
<p><span class="versionmodified changed"> 3.7 版本变更: </span> ''repeat'' 的默认值从 3 更改为 5。</p>
  
 
</div></dd></dl>
 
</div></dd></dl>
  
 
<dl>
 
<dl>
<dt><code>timeit.</code><code>default_timer</code><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">timeit.</span></span><span class="sig-name descname"><span class="pre">default_timer</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
<dd><p>The default timer, which is always [[../time#time|<code>time.perf_counter()</code>]].</p>
+
<dd><p>默认计时器,始终为 [[../time#time|time.perf_counter()]]</p>
 
<div class="versionchanged">
 
<div class="versionchanged">
  
<p><span class="versionmodified changed">在 3.3 版更改: </span>[[../time#time|<code>time.perf_counter()</code>]] is now the default timer.</p>
+
<p><span class="versionmodified changed"> 在 3.3 版更改: </span>[[../time#time|time.perf_counter()]] 现在是默认计时器。</p>
  
 
</div></dd></dl>
 
</div></dd></dl>
  
 
<dl>
 
<dl>
<dt>''class'' <code>timeit.</code><code>Timer</code><span class="sig-paren">(</span>''stmt='pass''', ''setup='pass''', ''timer=&lt;timer function&gt;'', ''globals=None''<span class="sig-paren">)</span></dt>
+
<dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">timeit.</span></span><span class="sig-name descname"><span class="pre">Timer</span></span><span class="sig-paren">(</span>''<span class="pre">stmt='pass'</span>'', ''<span class="pre">setup='pass'</span>'', ''<span class="pre">timer=&lt;timer</span> <span class="pre">function&gt;</span>'', ''<span class="pre">globals=None</span>''<span class="sig-paren">)</span></dt>
<dd><p>Class for timing execution speed of small code snippets.</p>
+
<dd><p>用于计时小代码片段执行速度的类。</p>
<p>The constructor takes a statement to be timed, an additional statement used
+
<p>构造函数接受一个要计时的语句、一个用于设置的附加语句和一个计时器函数。 两个语句都默认为 <code>'pass'</code>; 计时器功能是平台相关的(请参阅模块文档字符串)。 ''stmt'' ''setup'' 也可以包含由 <code>;</code> 或换行符分隔的多个语句,只要它们不包含多行字符串文字。 该语句将默认在 timeit 的命名空间内执行; 这种行为可以通过将命名空间传递给 ''globals'' 来控制。</p>
for setup, and a timer function. Both statements default to <code>'pass'</code>;
+
<p>要测量第一条语句的执行时间,请使用 [[#timeit.Timer.timeit|timeit()]] 方法。 [[#timeit.Timer.repeat|repeat()]] [[#timeit.Timer.autorange|autorange()]] 方法是多次调用 [[#timeit.Timer.timeit|timeit()]] 的便捷方法。</p>
the timer function is platform-dependent (see the module doc string).
+
<p>''setup'' 的执行时间不包括在整体定时执行运行中。</p>
''stmt'' and ''setup'' may also contain multiple statements separated by <code>;</code>
+
<p>''stmt'' ''setup'' 参数也可以采用无需参数即可调用的对象。 这会将对它们的调用嵌入到一个定时器函数中,然后由 [[#timeit.Timer.timeit|timeit()]] 执行。 请注意,在这种情况下,由于额外的函数调用,计时开销会稍大一些。</p>
or newlines, as long as they don't contain multi-line string literals. The
 
statement will by default be executed within timeit's namespace; this behavior
 
can be controlled by passing a namespace to ''globals''.</p>
 
<p>To measure the execution time of the first statement, use the [[#timeit.Timer.timeit|<code>timeit()</code>]]
 
method. The [[#timeit.Timer.repeat|<code>repeat()</code>]] and [[#timeit.Timer.autorange|<code>autorange()</code>]] methods are convenience
 
methods to call [[#timeit.Timer.timeit|<code>timeit()</code>]] multiple times.</p>
 
<p>The execution time of ''setup'' is excluded from the overall timed execution run.</p>
 
<p>The ''stmt'' and ''setup'' parameters can also take objects that are callable
 
without arguments. This will embed calls to them in a timer function that
 
will then be executed by [[#timeit.Timer.timeit|<code>timeit()</code>]]. Note that the timing overhead is a
 
little larger in this case because of the extra function calls.</p>
 
 
<div class="versionchanged">
 
<div class="versionchanged">
  
<p><span class="versionmodified changed">在 3.5 版更改: </span>The optional ''globals'' parameter was added.</p>
+
<p><span class="versionmodified changed"> 在 3.5 版更改: </span> 添加了可选的 ''globals'' 参数。</p>
  
 
</div>
 
</div>
 
<dl>
 
<dl>
<dt><code>timeit</code><span class="sig-paren">(</span>''<span class="n">number</span><span class="o">=</span><span class="default_value">1000000</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">timeit</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">number</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">1000000</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Time ''number'' executions of the main statement. This executes the setup
+
<dd><p>主语句的执行时间为 ''number'' 次。 这将执行一次 setup 语句,然后返回多次执行主语句所需的时间,以秒为单位作为浮点数。 参数是循环的次数,默认为一百万。 main 语句、setup 语句和要使用的定时器函数被传递给构造函数。</p>
statement once, and then returns the time it takes to execute the main
 
statement a number of times, measured in seconds as a float.
 
The argument is the number of times through the loop, defaulting to one
 
million. The main statement, the setup statement and the timer function
 
to be used are passed to the constructor.</p>
 
 
<div class="admonition note">
 
<div class="admonition note">
  
<p>注解</p>
+
<p>笔记</p>
<p>By default, [[#timeit.Timer.timeit|<code>timeit()</code>]] temporarily turns off [[../../glossary#term-garbage-collection|<span class="xref std std-term">garbage
+
<p>默认情况下,[[#timeit.Timer.timeit|timeit()]]在计时期间暂时关闭[[../../glossary#term-garbage-collection|垃圾收集]]。 这种方法的优点是它使独立时序更具可比性。 缺点是 GC 可能是被测量函数性能的重要组成部分。 如果是这样,GC 可以作为 ''setup'' 字符串中的第一条语句重新启用。 例如:</p>
collection</span>]] during the timing. The advantage of this approach is that
 
it makes independent timings more comparable. The disadvantage is
 
that GC may be an important component of the performance of the
 
function being measured. If so, GC can be re-enabled as the first
 
statement in the ''setup'' string. For example:</p>
 
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>timeit.Timer('for i in range(10): oct(i)', 'gc.enable()').timeit()</pre>
+
<syntaxhighlight lang="python3">timeit.Timer('for i in range(10): oct(i)', 'gc.enable()').timeit()</syntaxhighlight>
  
 
</div>
 
</div>
第166行: 第136行:
  
 
<dl>
 
<dl>
<dt><code>autorange</code><span class="sig-paren">(</span>''<span class="n">callback</span><span class="o">=</span><span class="default_value">None</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">autorange</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">callback</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Automatically determine how many times to call [[#timeit.Timer.timeit|<code>timeit()</code>]].</p>
+
<dd><p>自动确定调用 [[#timeit.Timer.timeit|timeit()]] 的次数。</p>
<p>This is a convenience function that calls [[#timeit.Timer.timeit|<code>timeit()</code>]] repeatedly
+
<p>这是一个方便的函数,它重复调用 [[#timeit.Timer.timeit|timeit()]] 使总时间 &gt;= 0.2 秒,返回最终结果(循环次数,该循环次数所用的时间)。 它调用 [[#timeit.Timer.timeit|timeit()]] 从序列 1, 2, 5, 10, 20, 50, ... 递增的数字,直到花费的时间至少为 0.2 秒。</p>
so that the total time &gt;= 0.2 second, returning the eventual
+
<p>如果给出 ''callback'' 并且不是 <code>None</code>,它将在每次试验后用两个参数调用:<code>callback(number, time_taken)</code></p>
(number of loops, time taken for that number of loops). It calls
 
[[#timeit.Timer.timeit|<code>timeit()</code>]] with increasing numbers from the sequence 1, 2, 5,
 
10, 20, 50, ... until the time taken is at least 0.2 second.</p>
 
<p>If ''callback'' is given and is not <code>None</code>, it will be called after
 
each trial with two arguments: <code>callback(number, time_taken)</code>.</p>
 
 
<div class="versionadded">
 
<div class="versionadded">
  
<p><span class="versionmodified added">3.6 新版功能.</span></p>
+
<p><span class="versionmodified added">3.6 版中的新功能。</span></p>
  
 
</div></dd></dl>
 
</div></dd></dl>
  
 
<dl>
 
<dl>
<dt><code>repeat</code><span class="sig-paren">(</span>''<span class="n">repeat</span><span class="o">=</span><span class="default_value">5</span>'', ''<span class="n">number</span><span class="o">=</span><span class="default_value">1000000</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">repeat</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">repeat</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">5</span></span>'', ''<span class="n"><span class="pre">number</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">1000000</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Call [[#timeit.Timer.timeit|<code>timeit()</code>]] a few times.</p>
+
<dd><p>多次调用 [[#timeit.Timer.timeit|timeit()]]</p>
<p>This is a convenience function that calls the [[#timeit.Timer.timeit|<code>timeit()</code>]] repeatedly,
+
<p>这是一个方便的函数,它重复调用 [[#timeit.Timer.timeit|timeit()]],返回结果列表。 第一个参数指定调用 [[#timeit.Timer.timeit|timeit()]] 的次数。 第二个参数指定 [[#timeit.Timer.timeit|timeit()]] 的 ''number'' 参数。</p>
returning a list of results. The first argument specifies how many times
 
to call [[#timeit.Timer.timeit|<code>timeit()</code>]]. The second argument specifies the ''number''
 
argument for [[#timeit.Timer.timeit|<code>timeit()</code>]].</p>
 
 
<div class="admonition note">
 
<div class="admonition note">
  
<p>注解</p>
+
<p>笔记</p>
<p>It's tempting to calculate mean and standard deviation from the result
+
<p>从结果向量计算均值和标准差并报告这些是很诱人的。 但是,这不是很有用。 在典型情况下,最低值给出了机器运行给定代码片段的速度的下限; 结果向量中的较高值通常不是由 Python 速度的变化引起的,而是由干扰计时精度的其他进程引起的。 因此,结果的 [[../functions#min|min()]] 可能是您应该感兴趣的唯一数字。 之后,您应该查看整个向量并应用常识而不是统计数据。</p>
vector and report these. However, this is not very useful.
 
In a typical case, the lowest value gives a lower bound for how fast
 
your machine can run the given code snippet; higher values in the
 
result vector are typically not caused by variability in Python's
 
speed, but by other processes interfering with your timing accuracy.
 
So the [[../functions#min|<code>min()</code>]] of the result is probably the only number you
 
should be interested in. After that, you should look at the entire
 
vector and apply common sense rather than statistics.</p>
 
  
 
</div>
 
</div>
 
<div class="versionchanged">
 
<div class="versionchanged">
  
<p><span class="versionmodified changed">3.7 版更改: </span>Default value of ''repeat'' changed from 3 to 5.</p>
+
<p><span class="versionmodified changed"> 3.7 版本变更: </span> ''repeat'' 的默认值从 3 更改为 5。</p>
  
 
</div></dd></dl>
 
</div></dd></dl>
  
 
<dl>
 
<dl>
<dt><code>print_exc</code><span class="sig-paren">(</span>''<span class="n">file</span><span class="o">=</span><span class="default_value">None</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">print_exc</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">file</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Helper to print a traceback from the timed code.</p>
+
<dd><p>帮助从定时代码打印回溯。</p>
<p>Typical use:</p>
+
<p>典型用途:</p>
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>t = Timer(...)      # outside the try/except
+
<syntaxhighlight lang="python3">t = Timer(...)      # outside the try/except
 
try:
 
try:
 
     t.timeit(...)    # or t.repeat(...)
 
     t.timeit(...)    # or t.repeat(...)
 
except Exception:
 
except Exception:
     t.print_exc()</pre>
+
     t.print_exc()</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
<p>The advantage over the standard traceback is that source lines in the
+
<p>与标准回溯相比的优点是将显示编译模板中的源代码行。 可选的 ''file'' 参数指示发送回溯的位置; 它默认为 [[../sys#sys|sys.stderr]]</p></dd></dl>
compiled template will be displayed. The optional ''file'' argument directs
 
where the traceback is sent; it defaults to [[../sys#sys|<code>sys.stderr</code>]].</p></dd></dl>
 
 
</dd></dl>
 
</dd></dl>
  
第235行: 第187行:
  
 
<span id="timeit-command-line-interface"></span>
 
<span id="timeit-command-line-interface"></span>
== Command-Line Interface ==
+
== 命令行界面 ==
  
When called as a program from the command line, the following form is used:
+
当从命令行作为程序调用时,使用以下形式:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第243行: 第195行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>python -m timeit [-n N] [-r N] [-u U] [-s S] [-h] [statement ...]</pre>
+
<syntaxhighlight lang="python3">python -m timeit [-n N] [-r N] [-u U] [-s S] [-h] [statement ...]</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Where the following options are understood:
+
理解以下选项的地方:
  
; <span id="cmdoption-timeit-number"></span><code>-n</code><code> N</code><code>, </code><code>--number</code><code>=N</code>
+
; <span id="cmdoption-timeit-number"></span><span class="sig-name descname"><span class="pre">-n</span></span><span class="sig-prename descclassname"> <span class="pre">N</span></span><span class="sig-prename descclassname"><span class="pre">,</span> </span><span class="sig-name descname"><span class="pre">--number</span></span><span class="sig-prename descclassname"><span class="pre">=N</span></span>
: how many times to execute 'statement'
+
: 执行“语句”多少次
  
; <span id="cmdoption-timeit-repeat"></span><code>-r</code><code> N</code><code>, </code><code>--repeat</code><code>=N</code>
+
; <span id="cmdoption-timeit-repeat"></span><span class="sig-name descname"><span class="pre">-r</span></span><span class="sig-prename descclassname"> <span class="pre">N</span></span><span class="sig-prename descclassname"><span class="pre">,</span> </span><span class="sig-name descname"><span class="pre">--repeat</span></span><span class="sig-prename descclassname"><span class="pre">=N</span></span>
: how many times to repeat the timer (default 5)
+
: 重复计时器多少次(默认 5)
  
; <span id="cmdoption-timeit-setup"></span><code>-s</code><code> S</code><code>, </code><code>--setup</code><code>=S</code>
+
; <span id="cmdoption-timeit-setup"></span><span class="sig-name descname"><span class="pre">-s</span></span><span class="sig-prename descclassname"> <span class="pre">S</span></span><span class="sig-prename descclassname"><span class="pre">,</span> </span><span class="sig-name descname"><span class="pre">--setup</span></span><span class="sig-prename descclassname"><span class="pre">=S</span></span>
: statement to be executed once initially (default <code>pass</code>)
+
: 最初执行一次的语句(默认 <code>pass</code>
  
 
<dl>
 
<dl>
<dt><span id="cmdoption-timeit-process"></span><code>-p</code><code></code><code>, </code><code>--process</code><code></code></dt>
+
<dt><span id="cmdoption-timeit-process"></span><span class="sig-name descname"><span class="pre">-p</span></span><span class="sig-prename descclassname"></span><span class="sig-prename descclassname"><span class="pre">,</span> </span><span class="sig-name descname"><span class="pre">--process</span></span><span class="sig-prename descclassname"></span></dt>
<dd><p>measure process time, not wallclock time, using [[../time#time|<code>time.process_time()</code>]]
+
<dd><p>使用 [[../time#time|time.process_time()]] 代替默认的 [[../time#time|time.perf_counter()]] 测量进程时间,而不是挂钟时间</p>
instead of [[../time#time|<code>time.perf_counter()</code>]], which is the default</p>
 
 
<div class="versionadded">
 
<div class="versionadded">
  
<p><span class="versionmodified added">3.3 新版功能.</span></p>
+
<p><span class="versionmodified added">3.3 版中的新功能。</span></p>
  
 
</div></dd></dl>
 
</div></dd></dl>
  
 
<dl>
 
<dl>
<dt><span id="cmdoption-timeit-unit"></span><code>-u</code><code></code><code>, </code><code>--unit</code><code>=U</code></dt>
+
<dt><span id="cmdoption-timeit-unit"></span><span class="sig-name descname"><span class="pre">-u</span></span><span class="sig-prename descclassname"></span><span class="sig-prename descclassname"><span class="pre">,</span> </span><span class="sig-name descname"><span class="pre">--unit</span></span><span class="sig-prename descclassname"><span class="pre">=U</span></span></dt>
<dd><p>specify a time unit for timer output; can select nsec, usec, msec, or sec</p>
+
<dd><p>指定定时器输出的时间单位; 可以选择 nsec、usec、msec 或 sec</p>
 
<div class="versionadded">
 
<div class="versionadded">
  
<p><span class="versionmodified added">3.5 新版功能.</span></p>
+
<p><span class="versionmodified added">3.5 版中的新功能。</span></p>
  
 
</div></dd></dl>
 
</div></dd></dl>
  
; <span id="cmdoption-timeit-verbose"></span><code>-v</code><code></code><code>, </code><code>--verbose</code><code></code>
+
; <span id="cmdoption-timeit-verbose"></span><span class="sig-name descname"><span class="pre">-v</span></span><span class="sig-prename descclassname"></span><span class="sig-prename descclassname"><span class="pre">,</span> </span><span class="sig-name descname"><span class="pre">--verbose</span></span><span class="sig-prename descclassname"></span>
: print raw timing results; repeat for more digits precision
+
: 打印原始计时结果; 重复以获得更多数字精度
  
; <span id="cmdoption-timeit-help"></span><code>-h</code><code></code><code>, </code><code>--help</code><code></code>
+
; <span id="cmdoption-timeit-help"></span><span class="sig-name descname"><span class="pre">-h</span></span><span class="sig-prename descclassname"></span><span class="sig-prename descclassname"><span class="pre">,</span> </span><span class="sig-name descname"><span class="pre">--help</span></span><span class="sig-prename descclassname"></span>
: print a short usage message and exit
+
: 打印一个简短的使用信息并退出
  
A multi-line statement may be given by specifying each line as a separate
+
可以通过将每一行指定为单独的语句参数来给出多行语句; 通过将参数括在引号中并使用前导空格,可以使用缩进行。 多个 [[#cmdoption-timeit-s|-s]] 选项的处理方式类似。
statement argument; indented lines are possible by enclosing an argument in
 
quotes and using leading spaces. Multiple [[#cmdoption-timeit-s|<code>-s</code>]] options are treated
 
similarly.
 
  
If [[#cmdoption-timeit-n|<code>-n</code>]] is not given, a suitable number of loops is calculated by trying
+
如果未给出 [[#cmdoption-timeit-n|-n]],则通过尝试从序列 1、2、5、10、20、50 中增加数字来计算合适的循环次数,直到总时间至少为 0.2 秒。
increasing numbers from the sequence 1, 2, 5, 10, 20, 50, ... until the total
 
time is at least 0.2 seconds.
 
  
[[#timeit.default_timer|<code>default_timer()</code>]] measurements can be affected by other programs running on
+
[[#timeit.default_timer|default_timer()]] 测量值可能会受到同一台机器上运行的其他程序的影响,因此在需要精确计时时最好的做法是重复计时几次并使用最佳时间。 [[#cmdoption-timeit-r|-r]] 选项对此很有用; 在大多数情况下,5 次重复的默认值可能就足够了。 您可以使用 [[../time#time|time.process_time()]] 来测量 CPU 时间。
the same machine, so the best thing to do when accurate timing is necessary is
 
to repeat the timing a few times and use the best time. The [[#cmdoption-timeit-r|<code>-r</code>]]
 
option is good for this; the default of 5 repetitions is probably enough in
 
most cases. You can use [[../time#time|<code>time.process_time()</code>]] to measure CPU time.
 
  
 
<div class="admonition note">
 
<div class="admonition note">
  
注解
+
笔记
  
There is a certain baseline overhead associated with executing a pass statement.
+
执行 pass 语句有一定的基线开销。 此处的代码不会试图隐藏它,但您应该意识到这一点。 可以通过不带参数调用程序来测量基线开销,并且它可能因 Python 版本而异。
The code here doesn't try to hide it, but you should be aware of it. The
 
baseline overhead can be measured by invoking the program without arguments,
 
and it might differ between Python versions.
 
  
  
第315行: 第254行:
  
 
<span id="timeit-examples"></span>
 
<span id="timeit-examples"></span>
== Examples ==
+
== 例子 ==
  
It is possible to provide a setup statement that is executed only once at the beginning:
+
可以提供一个在开始时只执行一次的 setup 语句:
  
 
<div class="highlight-shell-session notranslate">
 
<div class="highlight-shell-session notranslate">
第323行: 第262行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>$ python -m timeit -s 'text = &quot;sample string&quot;; char = &quot;g&quot;'  'char in text'
+
<pre class="session">$ python -m timeit -s 'text = &quot;sample string&quot;; char = &quot;g&quot;'  'char in text'
 
5000000 loops, best of 5: 0.0877 usec per loop
 
5000000 loops, best of 5: 0.0877 usec per loop
 
$ python -m timeit -s 'text = &quot;sample string&quot;; char = &quot;g&quot;'  'text.find(char)'
 
$ python -m timeit -s 'text = &quot;sample string&quot;; char = &quot;g&quot;'  'text.find(char)'
第335行: 第274行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; import timeit
+
<syntaxhighlight lang="python3">>>> import timeit
&gt;&gt;&gt; timeit.timeit('char in text', setup='text = &quot;sample string&quot;; char = &quot;g&quot;')
+
>>> timeit.timeit('char in text', setup='text = "sample string"; char = "g"')
 
0.41440500499993504
 
0.41440500499993504
&gt;&gt;&gt; timeit.timeit('text.find(char)', setup='text = &quot;sample string&quot;; char = &quot;g&quot;')
+
>>> timeit.timeit('text.find(char)', setup='text = "sample string"; char = "g"')
1.7246671520006203</pre>
+
1.7246671520006203</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The same can be done using the [[#timeit.Timer|<code>Timer</code>]] class and its methods:
+
使用 [[#timeit.Timer|Timer]] 类及其方法也可以做到这一点:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第350行: 第289行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; import timeit
+
<syntaxhighlight lang="python3">>>> import timeit
&gt;&gt;&gt; t = timeit.Timer('char in text', setup='text = &quot;sample string&quot;; char = &quot;g&quot;')
+
>>> t = timeit.Timer('char in text', setup='text = "sample string"; char = "g"')
&gt;&gt;&gt; t.timeit()
+
>>> t.timeit()
 
0.3955516149999312
 
0.3955516149999312
&gt;&gt;&gt; t.repeat()
+
>>> t.repeat()
[0.40183617287970225, 0.37027556854118704, 0.38344867356679524, 0.3712595970846668, 0.37866875250654886]</pre>
+
[0.40183617287970225, 0.37027556854118704, 0.38344867356679524, 0.3712595970846668, 0.37866875250654886]</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The following examples show how to time expressions that contain multiple lines.
+
以下示例显示如何对包含多行的表达式计时。 在这里,我们比较了使用 [[../functions#hasattr|hasattr()]] 与使用的成本。 [[../../reference/compound_stmts#try|try]]/[[../../reference/compound_stmts#except|except]] 测试缺少和存在的对象属性:
Here we compare the cost of using [[../functions#hasattr|<code>hasattr()</code>]] vs. [[../../reference/compound_stmts#try|<code>try</code>]]/[[../../reference/compound_stmts#except|<code>except</code>]]
 
to test for missing and present object attributes:
 
  
 
<div class="highlight-shell-session notranslate">
 
<div class="highlight-shell-session notranslate">
第368行: 第305行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>$ python -m timeit 'try:' '  str.__bool__' 'except AttributeError:' '  pass'
+
<pre class="session">$ python -m timeit 'try:' '  str.__bool__' 'except AttributeError:' '  pass'
 
20000 loops, best of 5: 15.7 usec per loop
 
20000 loops, best of 5: 15.7 usec per loop
 
$ python -m timeit 'if hasattr(str, &quot;__bool__&quot;): pass'
 
$ python -m timeit 'if hasattr(str, &quot;__bool__&quot;): pass'
第385行: 第322行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; import timeit
+
<syntaxhighlight lang="python3">>>> import timeit
&gt;&gt;&gt; # attribute is missing
+
>>> # attribute is missing
&gt;&gt;&gt; s = &quot;&quot;&quot;\
+
>>> s = """\
 
... try:
 
... try:
 
...    str.__bool__
 
...    str.__bool__
 
... except AttributeError:
 
... except AttributeError:
 
...    pass
 
...    pass
... &quot;&quot;&quot;
+
... """
&gt;&gt;&gt; timeit.timeit(stmt=s, number=100000)
+
>>> timeit.timeit(stmt=s, number=100000)
 
0.9138244460009446
 
0.9138244460009446
&gt;&gt;&gt; s = &quot;if hasattr(str, '__bool__'): pass&quot;
+
>>> s = "if hasattr(str, '__bool__'): pass"
&gt;&gt;&gt; timeit.timeit(stmt=s, number=100000)
+
>>> timeit.timeit(stmt=s, number=100000)
 
0.5829014980008651
 
0.5829014980008651
&gt;&gt;&gt;
+
>>>
&gt;&gt;&gt; # attribute is present
+
>>> # attribute is present
&gt;&gt;&gt; s = &quot;&quot;&quot;\
+
>>> s = """\
 
... try:
 
... try:
 
...    int.__bool__
 
...    int.__bool__
 
... except AttributeError:
 
... except AttributeError:
 
...    pass
 
...    pass
... &quot;&quot;&quot;
+
... """
&gt;&gt;&gt; timeit.timeit(stmt=s, number=100000)
+
>>> timeit.timeit(stmt=s, number=100000)
 
0.04215312199994514
 
0.04215312199994514
&gt;&gt;&gt; s = &quot;if hasattr(int, '__bool__'): pass&quot;
+
>>> s = "if hasattr(int, '__bool__'): pass"
&gt;&gt;&gt; timeit.timeit(stmt=s, number=100000)
+
>>> timeit.timeit(stmt=s, number=100000)
0.08588060699912603</pre>
+
0.08588060699912603</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
To give the [[#module-timeit|<code>timeit</code>]] module access to functions you define, you can pass a
+
要让 [[#module-timeit|timeit]] 模块访问您定义的函数,您可以传递包含导入语句的 ''setup'' 参数:
''setup'' parameter which contains an import statement:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第422行: 第358行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>def test():
+
<syntaxhighlight lang="python3">def test():
     &quot;&quot;&quot;Stupid test function&quot;&quot;&quot;
+
     """Stupid test function"""
 
     L = [i for i in range(100)]
 
     L = [i for i in range(100)]
  
 
if __name__ == '__main__':
 
if __name__ == '__main__':
 
     import timeit
 
     import timeit
     print(timeit.timeit(&quot;test()&quot;, setup=&quot;from __main__ import test&quot;))</pre>
+
     print(timeit.timeit("test()", setup="from __main__ import test"))</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Another option is to pass [[../functions#globals|<code>globals()</code>]] to the ''globals'' parameter, which will cause the code
+
另一种选择是将 [[../functions#globals|globals()]] 传递给 ''globals'' 参数,这将导致代码在您当前的全局命名空间中执行。 这比单独指定导入更方便:
to be executed within your current global namespace. This can be more convenient
 
than individually specifying imports:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第441行: 第375行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>def f(x):
+
<syntaxhighlight lang="python3">def f(x):
 
     return x**2
 
     return x**2
 
def g(x):
 
def g(x):
第449行: 第383行:
  
 
import timeit
 
import timeit
print(timeit.timeit('[func(42) for func in (f,g,h)]', globals=globals()))</pre>
+
print(timeit.timeit('[func(42) for func in (f,g,h)]', globals=globals()))</syntaxhighlight>
 +
 
 +
</div>
  
 
</div>
 
</div>
第456行: 第392行:
  
 
</div>
 
</div>
 +
<div class="clearer">
 +
 +
  
 
</div>
 
</div>
  
[[Category:Python 3.9 中文文档]]
+
[[Category:Python 3.9 文档]]

2021年10月31日 (日) 04:53的最新版本

timeit — 测量小代码片段的执行时间

源代码: :source:`Lib/timeit.py`



该模块提供了一种简单的方法来计时一小段 Python 代码。 它既有 命令行接口 ,也有 可调用 接口。 它避免了许多用于测量执行时间的常见陷阱。 另请参阅 O'Reilly 出版的 Python Cookbook 第二版中 Tim Peters 对“算法”章节的介绍。

基本示例

以下示例显示了如何使用 命令行界面 来比较三种不同的表达式:

$ python3 -m timeit '"-".join(str(n) for n in range(100))'
10000 loops, best of 5: 30.2 usec per loop
$ python3 -m timeit '"-".join([str(n) for n in range(100)])'
10000 loops, best of 5: 27.5 usec per loop
$ python3 -m timeit '"-".join(map(str, range(100)))'
10000 loops, best of 5: 23.2 usec per loop

这可以通过 Python 接口 实现:

>>> import timeit
>>> timeit.timeit('"-".join(str(n) for n in range(100))', number=10000)
0.3018611848820001
>>> timeit.timeit('"-".join([str(n) for n in range(100)])', number=10000)
0.2727368790656328
>>> timeit.timeit('"-".join(map(str, range(100)))', number=10000)
0.23702679807320237

也可以从 Python 接口 传递一个可调用对象:

>>> timeit.timeit(lambda: "-".join(map(str, range(100))), number=10000)
0.19665591977536678

但是请注意,只有在使用命令行界面时, timeit() 才会自动确定重复次数。 在 示例 部分,您可以找到更高级的示例。


Python接口

该模块定义了三个便利函数和一个公共类:

timeit.timeit(stmt='pass', setup='pass', timer=<default timer>, number=1000000, globals=None)

使用给定的语句、setup 代码和 timer 函数创建一个 Timer 实例,并使用 编号运行其 timeit() 方法 处决。 可选的 globals 参数指定执行代码的命名空间。

在 3.5 版更改: 添加了可选的 globals 参数。

timeit.repeat(stmt='pass', setup='pass', timer=<default timer>, repeat=5, number=1000000, globals=None)

使用给定的语句、setup 代码和 timer 函数创建一个 Timer 实例,并使用给定的 运行其 repeat() 方法]repeat 计数和 number 次执行。 可选的 globals 参数指定执行代码的命名空间。

在 3.5 版更改: 添加了可选的 globals 参数。

3.7 版本变更: repeat 的默认值从 3 更改为 5。

timeit.default_timer()

默认计时器,始终为 time.perf_counter()

在 3.3 版更改: time.perf_counter() 现在是默认计时器。

class timeit.Timer(stmt='pass', setup='pass', timer=<timer function>, globals=None)

用于计时小代码片段执行速度的类。

构造函数接受一个要计时的语句、一个用于设置的附加语句和一个计时器函数。 两个语句都默认为 'pass'; 计时器功能是平台相关的(请参阅模块文档字符串)。 stmtsetup 也可以包含由 ; 或换行符分隔的多个语句,只要它们不包含多行字符串文字。 该语句将默认在 timeit 的命名空间内执行; 这种行为可以通过将命名空间传递给 globals 来控制。

要测量第一条语句的执行时间,请使用 timeit() 方法。 repeat()autorange() 方法是多次调用 timeit() 的便捷方法。

setup 的执行时间不包括在整体定时执行运行中。

stmtsetup 参数也可以采用无需参数即可调用的对象。 这会将对它们的调用嵌入到一个定时器函数中,然后由 timeit() 执行。 请注意,在这种情况下,由于额外的函数调用,计时开销会稍大一些。

在 3.5 版更改: 添加了可选的 globals 参数。

timeit(number=1000000)

主语句的执行时间为 number 次。 这将执行一次 setup 语句,然后返回多次执行主语句所需的时间,以秒为单位作为浮点数。 参数是循环的次数,默认为一百万。 main 语句、setup 语句和要使用的定时器函数被传递给构造函数。

笔记

默认情况下,timeit()在计时期间暂时关闭垃圾收集。 这种方法的优点是它使独立时序更具可比性。 缺点是 GC 可能是被测量函数性能的重要组成部分。 如果是这样,GC 可以作为 setup 字符串中的第一条语句重新启用。 例如:

timeit.Timer('for i in range(10): oct(i)', 'gc.enable()').timeit()
autorange(callback=None)

自动确定调用 timeit() 的次数。

这是一个方便的函数,它重复调用 timeit() 使总时间 >= 0.2 秒,返回最终结果(循环次数,该循环次数所用的时间)。 它调用 timeit() 从序列 1, 2, 5, 10, 20, 50, ... 递增的数字,直到花费的时间至少为 0.2 秒。

如果给出 callback 并且不是 None,它将在每次试验后用两个参数调用:callback(number, time_taken)

3.6 版中的新功能。

repeat(repeat=5, number=1000000)

多次调用 timeit()

这是一个方便的函数,它重复调用 timeit(),返回结果列表。 第一个参数指定调用 timeit() 的次数。 第二个参数指定 timeit()number 参数。

笔记

从结果向量计算均值和标准差并报告这些是很诱人的。 但是,这不是很有用。 在典型情况下,最低值给出了机器运行给定代码片段的速度的下限; 结果向量中的较高值通常不是由 Python 速度的变化引起的,而是由干扰计时精度的其他进程引起的。 因此,结果的 min() 可能是您应该感兴趣的唯一数字。 之后,您应该查看整个向量并应用常识而不是统计数据。

3.7 版本变更: repeat 的默认值从 3 更改为 5。

print_exc(file=None)

帮助从定时代码打印回溯。

典型用途:

t = Timer(...)       # outside the try/except
try:
    t.timeit(...)    # or t.repeat(...)
except Exception:
    t.print_exc()

与标准回溯相比的优点是将显示编译模板中的源代码行。 可选的 file 参数指示发送回溯的位置; 它默认为 sys.stderr


命令行界面

当从命令行作为程序调用时,使用以下形式:

python -m timeit [-n N] [-r N] [-u U] [-s S] [-h] [statement ...]

理解以下选项的地方:

-n N, --number=N
执行“语句”多少次
-r N, --repeat=N
重复计时器多少次(默认 5)
-s S, --setup=S
最初执行一次的语句(默认 pass
-p, --process

使用 time.process_time() 代替默认的 time.perf_counter() 测量进程时间,而不是挂钟时间

3.3 版中的新功能。

-u, --unit=U

指定定时器输出的时间单位; 可以选择 nsec、usec、msec 或 sec

3.5 版中的新功能。

-v, --verbose
打印原始计时结果; 重复以获得更多数字精度
-h, --help
打印一个简短的使用信息并退出

可以通过将每一行指定为单独的语句参数来给出多行语句; 通过将参数括在引号中并使用前导空格,可以使用缩进行。 多个 -s 选项的处理方式类似。

如果未给出 -n,则通过尝试从序列 1、2、5、10、20、50 中增加数字来计算合适的循环次数,直到总时间至少为 0.2 秒。

default_timer() 测量值可能会受到同一台机器上运行的其他程序的影响,因此在需要精确计时时最好的做法是重复计时几次并使用最佳时间。 -r 选项对此很有用; 在大多数情况下,5 次重复的默认值可能就足够了。 您可以使用 time.process_time() 来测量 CPU 时间。

笔记

执行 pass 语句有一定的基线开销。 此处的代码不会试图隐藏它,但您应该意识到这一点。 可以通过不带参数调用程序来测量基线开销,并且它可能因 Python 版本而异。


例子

可以提供一个在开始时只执行一次的 setup 语句:

$ python -m timeit -s 'text = "sample string"; char = "g"'  'char in text'
5000000 loops, best of 5: 0.0877 usec per loop
$ python -m timeit -s 'text = "sample string"; char = "g"'  'text.find(char)'
1000000 loops, best of 5: 0.342 usec per loop
>>> import timeit
>>> timeit.timeit('char in text', setup='text = "sample string"; char = "g"')
0.41440500499993504
>>> timeit.timeit('text.find(char)', setup='text = "sample string"; char = "g"')
1.7246671520006203

使用 Timer 类及其方法也可以做到这一点:

>>> import timeit
>>> t = timeit.Timer('char in text', setup='text = "sample string"; char = "g"')
>>> t.timeit()
0.3955516149999312
>>> t.repeat()
[0.40183617287970225, 0.37027556854118704, 0.38344867356679524, 0.3712595970846668, 0.37866875250654886]

以下示例显示如何对包含多行的表达式计时。 在这里,我们比较了使用 hasattr() 与使用的成本。 try/except 测试缺少和存在的对象属性:

$ python -m timeit 'try:' '  str.__bool__' 'except AttributeError:' '  pass'
20000 loops, best of 5: 15.7 usec per loop
$ python -m timeit 'if hasattr(str, "__bool__"): pass'
50000 loops, best of 5: 4.26 usec per loop

$ python -m timeit 'try:' '  int.__bool__' 'except AttributeError:' '  pass'
200000 loops, best of 5: 1.43 usec per loop
$ python -m timeit 'if hasattr(int, "__bool__"): pass'
100000 loops, best of 5: 2.23 usec per loop
>>> import timeit
>>> # attribute is missing
>>> s = """\
... try:
...     str.__bool__
... except AttributeError:
...     pass
... """
>>> timeit.timeit(stmt=s, number=100000)
0.9138244460009446
>>> s = "if hasattr(str, '__bool__'): pass"
>>> timeit.timeit(stmt=s, number=100000)
0.5829014980008651
>>>
>>> # attribute is present
>>> s = """\
... try:
...     int.__bool__
... except AttributeError:
...     pass
... """
>>> timeit.timeit(stmt=s, number=100000)
0.04215312199994514
>>> s = "if hasattr(int, '__bool__'): pass"
>>> timeit.timeit(stmt=s, number=100000)
0.08588060699912603

要让 timeit 模块访问您定义的函数,您可以传递包含导入语句的 setup 参数:

def test():
    """Stupid test function"""
    L = [i for i in range(100)]

if __name__ == '__main__':
    import timeit
    print(timeit.timeit("test()", setup="from __main__ import test"))

另一种选择是将 globals() 传递给 globals 参数,这将导致代码在您当前的全局命名空间中执行。 这比单独指定导入更方便:

def f(x):
    return x**2
def g(x):
    return x**4
def h(x):
    return x**8

import timeit
print(timeit.timeit('[func(42) for func in (f,g,h)]', globals=globals()))