数据结构与算法(python):python内置性能度量模块timeit

1、介绍

该模块为小段 p y t h o n python python 代码提供一种简单的计时方法。它能够避免许多测量执行时间的常见的陷阱。该模块为用户提供了命令行接口调用接口


2、命令行接口

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

#	-n N, --number=N
#	执行语句的次数

#	-r N, --repeat=N
#	重复 timer 的次数 (默认为 3)

#	-s S, --setup=S
#	语句最初执行一次 (默认 pass)

#	-p, --process
#	测量进程时间而不是时钟时间,使用 time.process_time() 取代默认的 time.perf_counter()

# 在3.3版本中:

#	-t, --time
#	使用time.time() (弃用)

#	-u, --unit=U
#	为计时器输出指定单位,可以选择微秒,毫秒,秒。

#	在3.5.版本中

#	-c, --clock
#	使用 time.clock() (弃用)

#	-v, --verbose
#	打印原始计时结果;重复获取更高数字精度

#	-h, --help
#	打印简短的使用信息并退出

以下官方示例演示如何使用命令行接口来比较三个不同的表达式

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

以下为 p y t h o n python 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

3、python 接口

该模块定义了三个函数和一个 p u b l i c public public 类。

3.1、函数和类

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

使用给定语句创建一个 T i m e r Timer Timer 实例,安装代码和 t i m e r timer timer 函数,并运行 t i m e i t ( ) timeit() timeit() 方法 n u m b e r number number 次。可选 g l o b a l s globals globals 参数指定要在其中执行代码的命名空间。可选 g l o b a l s globals globals 参数在 3.5 3.5 3.5 版本中被添加。

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

使用给定语句创建一个 T i m e r Timer Timer 实例,安装代码和 t i m e r timer timer 函数,并按照重复次数和执行次数运行 r e p e a t ( ) repeat() repeat() 方法。可选 g l o b a l s globals globals 参数指定要在其中执行代码的命名空间。可选 g l o b a l s globals globals 参数在 3.5 3.5 3.5 版本中被添加。

timeit.default_timer()

默认 t i m e r timer timer 一般为 t i m e . p e r f _ c o u n t e r ( ) time.perf\_counter() time.perf_counter()

3.3 3.3 3.3 版本以后 t i m e . p e r f _ c o u n t e r ( ) time.perf\_counter() time.perf_counter() 为默认 t i m e r timer timer

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

为小代码段执行速度计时的类。

构造函数接收要计时的语句、用于安装的附加语句和 t i m e r timer timer 函数。两个语句都默认为 p a s s pass pass t i m e r timer timer 函数依赖于平台(参见模块文档字符串)。 s t m t stmt stmt s e t u p setup setup 还可能包含多个用;或者换行符分隔的语句,只要它们不包含多行字符串。默认情况下,该语句将在 t i m e i t timeit timeit 命名空间内执行。这可以通过将命名空间传递给 g l o b a l s globals globals 来控制。

要度量第一条语句的执行时间,使用 t i m e i t ( ) timeit() timeit() 方法。 r e p e a t ( ) repeat() repeat() a u t o r a n g e ( ) autorange() autorange() 方法是多次调用 t i m e i t ( ) timeit() timeit() 的方便的方法。

s e t u p setup setup 程序的执行时间不包括在整个执行时间中。

s t m t stmt stmt s e t u p setup setup 参数也可以接受不带参数的可调用对象。这将在 t i m e r timer timer 函数中嵌入对它们的调用,然后 t i m e r timer timer 函数将由 t i m e i t ( ) timeit() timeit() 执行。注意,在这种情况下,由于额外的函数调用,计时开销稍微大一点。

timeit(number=1000000)

主语句执行的次数。它只执行一次安装语句,然后返回多次执行主语句所需的时间,该时间是以秒为单位的浮点数。参数是循环的次数,默认为 100 100 100 万次。将主语句、 s e t u p setup setup 语句和要使用的 t i m e r timer timer 函数传递给构造函数。

注意:默认情况下, t i m e i t ( ) timeit() timeit() 在计时期间暂时关闭 g a r b a g e   c o l l e c t i o n garbage~collection garbage collection。这种方法的优点是它使独立的计时更具有可比性。这个缺点是 G C GC GC 可能是正在测量的函数性能的一个重要组成部分。如果是这样的话, G C GC GC 可以作为 s e t u p setup setup 字符串中的第一个语句重新启用。例如:
timeit.Timer('for i in range(10): oct(i)', 'gc.enable()').timeit()

autorange(callback=None)

自动确定调用 t i m e i t ( ) timeit() timeit() 的次数。

这是一个方便的函数,它反复调用 t i m e i t ( ) timeit() timeit(),以便总时间 ≥ 0.2 \ge0.2 0.2 秒,返回最终的时间(循环数,循环所花费的时间)。它调用 t i m e i t ( ) timeit() timeit() 10 10 10 的连续幂次,最多可达 10 10 10 亿,直到所需时间至少为 0.2 0.2 0.2 秒,或达到最大值为止。

如果回调是给定的,而且不是 N o n e None None,则在每次试用之后都会调用回调,其中包含两个参数: c a l l b a c k ( n u m b e r , t i m e _ t a k e n ) callback(number, time\_taken) callback(number,time_taken)

repeat(repeat=3, number=1000000)

调用 t i m e i t ( ) timeit() timeit() 几次

这是一个方便的函数,它反复调用 t i m e i t ( ) timeit() timeit(),返回结果列表。第一个参数指定调用 t i m e i t ( ) timeit() timeit() 的次数。第二个参数指定 t i m e i t ( ) timeit() timeit() n u m b e r number number 参数。

注意,计算并报告结果向量的均值和标准差是很有诱惑力的。然而,这并不十分有用。在典型情况下,最低值为机器运行给定代码段的速度提供了一个下限;结果向量中较高的值通常不是由 P y t h o n Python Python 速度的变化造成的,而是其他进程干扰了计时精度造成的。因此,结果的 m i n ( ) min() min() 可能是应该感兴趣的唯一数字。在此之后,应该查看整个向量,并应用常识而不是统计数据。

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

与标准的回溯相比,它的优点是将显示编译模板中的源行。可选 f i l e file file 参数指示回溯的发送位置,它默认为 s y s . s t d e r r sys.stderr sys.stderr


3.2、官方示例

提供只在开头执行一次的安装语句

$ python -m timeit -s 'text = "sample string"; char = "g"'  'char in text'
10000000 loops, best of 3: 0.0877 usec per loop
$ python -m timeit -s 'text = "sample string"; char = "g"'  'text.find(char)'
1000000 loops, best of 3: 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

使用 T i m e r Timer Timer 类及其方法也可以这样做

>>> import timeit
>>> t = timeit.Timer('char in text', setup='text = "sample string"; char = "g"')
>>> t.timeit()
0.3955516149999312
>>> t.repeat()
[0.40193588800002544, 0.3960157959998014, 0.39594301399984033]

下面的示例演示如何对包含多行的表达式进行计时。在这里,比较了使用 h a s a t t r ( ) hasattr() hasattr() t r y / e x c e p t try/except try/except 测试缺少的对象属性和表示对象属性的成本。

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

$ python -m timeit 'try:' '  int.__bool__' 'except AttributeError:' '  pass'
1000000 loops, best of 3: 1.43 usec per loop
$ python -m timeit 'if hasattr(int, "__bool__"): pass'
100000 loops, best of 3: 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

要让 t i m e i t timeit timeit 模块访问您定义的函数,您可以传递一个 s e t u p setup setup 参数,该参数包含一个 i m p o r t import import 语句。

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"))

另一个选项是将 g l o b a l s ( ) globals() globals() 传递给 g l o b a l s 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()))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值