timeit 对比 timing d

2024-06-06 07:36:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我想计时一些代码。首先,我使用了一个计时装饰器:

#!/usr/bin/env python

import time
from itertools import izip
from random import shuffle

def timing_val(func):
    def wrapper(*arg, **kw):
        '''source: http://www.daniweb.com/code/snippet368.html'''
        t1 = time.time()
        res = func(*arg, **kw)
        t2 = time.time()
        return (t2 - t1), res, func.__name__
    return wrapper

@timing_val
def time_izip(alist, n):
    i = iter(alist)
    return [x for x in izip(*[i] * n)]

@timing_val
def time_indexing(alist, n):
    return [alist[i:i + n] for i in range(0, len(alist), n)]

func_list = [locals()[key] for key in locals().keys()
             if callable(locals()[key]) and key.startswith('time')]
shuffle(func_list)  # Shuffle, just in case the order matters

alist = range(1000000)
times = []
for f in func_list:
    times.append(f(alist, 31))

times.sort(key=lambda x: x[0])
for (time, result, func_name) in times:
    print '%s took %0.3fms.' % (func_name, time * 1000.)

收益率

% test.py
time_indexing took 73.230ms.
time_izip took 122.057ms.

在这里我用时间:

%  python - m timeit - s '' 'alist=range(1000000);[alist[i:i+31] for i in range(0, len(alist), 31)]'
10 loops, best of 3:
    64 msec per loop
% python - m timeit - s 'from itertools import izip' 'alist=range(1000000);i=iter(alist);[x for x in izip(*[i]*31)]'
10 loops, best of 3:
    66.5 msec per loop

使用timeit,结果实际上是相同的,但是使用timeing decorator,似乎time_indexingtime_izip快。

是什么造成了这种差异?

两种方法都可信吗?

如果是,是哪一个?


Tags: keyinfromimportforreturntimedef
3条回答

我将使用一个计时装饰器,因为您可以使用注释在代码周围散布计时,而不是让代码与计时逻辑混淆。

import time

def timeit(f):

    def timed(*args, **kw):

        ts = time.time()
        result = f(*args, **kw)
        te = time.time()

        print 'func:%r args:[%r, %r] took: %2.4f sec' % \
          (f.__name__, args, kw, te-ts)
        return result

    return timed

使用decorator很容易使用注释。

@timeit
def compute_magic(n):
     #function definition
     #....

或者重新命名要计时的函数。

compute_magic = timeit(compute_magic)

使用functools中的包装来改进Matt Alcock的答案。

from functools import wraps
from time import time

def timing(f):
    @wraps(f)
    def wrap(*args, **kw):
        ts = time()
        result = f(*args, **kw)
        te = time()
        print 'func:%r args:[%r, %r] took: %2.4f sec' % \
          (f.__name__, args, kw, te-ts)
        return result
    return wrap

例如:

@timing
def f(a):
    for _ in range(a):
        i = 0
    return -1

调用用@timing包装的方法f

func:'f' args:[(100000000,), {}] took: 14.2240 sec
f(100000000)

这样做的好处是它保留了原始函数的属性;也就是说,像函数名和docstring这样的元数据正确地保留在返回的函数上。

利用时间。不止一次地进行测试给了我更好的结果。

func_list=[locals()[key] for key in locals().keys() 
           if callable(locals()[key]) and key.startswith('time')]

alist=range(1000000)
times=[]
for f in func_list:
    n = 10
    times.append( min(  t for t,_,_ in (f(alist,31) for i in range(n)))) 

for (time,func_name) in zip(times, func_list):
    print '%s took %0.3fms.' % (func_name, time*1000.)

->

<function wrapper at 0x01FCB5F0> took 39.000ms.
<function wrapper at 0x01FCB670> took 41.000ms.

相关问题 更多 >