Python提供了一个timeit.timeit()函数用于计算函数的运行时间,这使得我们在项目开发中很方便的设计profiling并根据结果做相应的优化, 其定义如下:
timeit.timeit(stmt='pass', setup='pass', timer=<default timer>, number=1000000) Create a Timer instance with the given statement, setup code and timer function and run its timeit() method with number executions. New in version 2.6.
例如,假设我们在某个项目中要统计并存储访问过的url,一个可能的实现如下所示:
1 class UrlStatistics: 2 def __init__(self): 3 self.visitedSites = dict() 4 5 def visit(self, url): 6 if url in self.visitedSites: 7 self.visitedSites[url] += 1 8 else: 9 self.visitedSites[url] = 1 10 11 def mostFrequentVisitedSites(self, n=10): 12 sortedSites = sorted(self.visitedSites.items(), 13 key=lambda pair: pair[1], reverse=True) 14 return [(url, visits) for url, visits in sortedSites[:n]]
上面示例代码中用一个dict变量存储所有访问过的url(line 2), 函数visit() 将每一个新访问的的url计入我们的统计当中(line5~9), 函数mostFrequentVisitedSites()返回访问最频繁的前十名url(line 11~14). 为了使用timeit.timeit()函数计算visit()或mostFrequentVisitedSites()执行效率,我们需要让该函数反复执行,因此我们还需要以某种方式来反复得到不同或相同的URL。 下面的get_url_name()函数随机从英文字母表选取3-7个字符并拼接成URL, test_visit()函数用于调用UrlStatistics.visit(), 最后我们用timeit.timeit()调用test_visit()函数并设定调用次数,最后得到运行时间:
1 def get_url_name(): 2 prefix = 'www' 3 suffix = 'com' 4 name = ''.join([random.choice(string.ascii_lowercase) 5 for i in range(random.randint(3, 7))]) 6 return '.'.join([prefix, name, suffix]) 7 8 9 def test_visit(): 10 urlStats = UrlStatistics() 11 urlStats.visit(get_url_name()) 12 13 14 if __name__ == '__main__': 15 print(timeit.timeit('test_visit()', 16 setup='from __main__ import test_visit', 17 number=600000))
结果如下:
stephenw@stephenw-devbox1:~/pyTest$ ./timeitTest.py
8.078887998002756
考虑到python中collections模块中的defaultdict可以让visit()函数看上去更简洁,我们可做如下修改:
class UrlStatistics: def __init__(self): self.visitedSites = defaultdict(int) def visit(self, url): self.visitedSites[url] += 1
相应的,由timeit.timeit()得到的运行时间为 8.326297112002067, 可见使用defaultdict()后,效率降低了
最后,timeit模块还提供了命令行接口来实现同样的功能(结果和上面略有差异):
stephenw@stephenw-devbox1:~/pyTest$ python -m timeit -n 600000 "from timeitTest import test_visit; test_visit()"
600000 loops, best of 3: 9.83 usec per loop