继之前分别手动实现和用bisect库实现二分查找后,测试下它们执行时间究竟差别多大。
首先搞个装饰器计算时间:
def timefunc(repeat_times=1):
if callable(repeat_times): # @timefunc
func = repeat_times
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
func(*args, **kwargs)
stop = time.time()
# print(f'time cost: {stop - start:.5f} s')
return stop - start
return wrapper
else: # @timefunc(...)
assert repeat_times >= 1
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
[func(*args, **kwargs) for _ in range(repeat_times)]
stop = time.time()
# print(f'average time cost: {(stop - start) / repeat_times:.5f} s')
return (stop - start) / repeat_times
return wrapper
return decorator
这是一个装饰器基本的实现,使用了一组if-else
来区分带参数和不带参数的装饰器。(自卖自夸:D 我之前也写了一篇文章简单介绍了装饰器)
现在使用带参数的装饰器来测试平均执行时间。
@timefunc(repeat_times=100)
def test_manual(nums):
k = random.choice(nums)
binary_search_manual(nums, k)
@timefunc(repeat_times=100)
def test_bisect(nums):
k = random.choice(nums)
binary_search_bisect(nums, k)
次数暂定100
次。其中的binary_search_manual(nums, k)
和binary_search_bisect(nums, k)
参考之前的使用bisect实现二分查找这篇文章。
输入 list 长度取1000000
,然后运行:
if __name__ == "__main__":
nums = list(range(1000000))
t1 = test_manual(nums)
print(f'average time cost: {t1:.4e} s')
t2 = test_bisect(nums)
print(f'average time cost: {t2:.4e} s')
print(f'difference: {abs(t1-t2):.4e} s')
在我的电脑上运行得到的结果如下:
average time cost: 1.0493e-04 s
average time cost: 1.3177e-05 s
difference: 9.1753e-05 s
库函数的明显快一些,不过在1000000这个量级差别不大,毕竟是二分算法。
参考资料:
- 装饰器 - 廖雪峰的官方网站
- bisect 官方文档