第十六章:开发工具-timeit:测量小段Python代码执行的时间-将值存储在字典中

it2022-05-05  89

16.9.3 将值存储在字典中 下一个例子更为复杂,它比较了使用不同方法以大量值填充一个字典所需的时间。首先,需要一些常量来配置Timer。setup_statement变量初始化一个元组列表,这些元组中包含主语句用来构建字典的字符串和整数,字符串被用作键,整数被存储为关联的值。

import timeit import textwrap # A few constants range_size = 1000 count = 1000 setup_statement = ';'.join([ "l = [(str(x),x) for x in range(1000)]", "d = {}", ]) # 这里定义了一个工具函数show_results(),它采用一种有用的格式来打印结果。timeit() # 方法返回反复执行这个语句所花费的时间。show_results()的输出将这个值转换为每次 # 迭代花费的时间,然后进一步将这个值缩减为在字典中存储一项所花费的平均时间。 def show_results(result): "Print microseconds per pass and per item." global count,range_size per_pass = 1000000 * (result / count) print('{:6.2f} usec/pass'.format(per_pass),end=' ') per_item = per_pass / range_size print('{:6.2f} usec/item'.format(per_item)) print("{} items".format(range_size)) print('{} iterations'.format(count)) print() # 为了建立一个基准,测试的第一个配置使用了__setitem__()。所有其他版本都不会覆盖 # 字典中已经有的值,所以这个简单版本应该是最快的。 # Timer的第一个参数是一个多行的字符串,这里保留了空白符,以确保运行时函数能正确 # 地解析这个 字符串。第二个参数是一个常量,用来初始化值列表和字典。 # Using __setitem__ without checking for existing values first print('__setitem__:',end=' ') t = timeit.Timer( textwrap.dedent( """ for s, i in l: d[s] = i """), setup_statement, ) show_results(t.timeit(number=count)) # 下一个版本使用setdefault()确保字典中已有的值不会被覆盖。 # Using setdefault print('setdefault:',end=' ') t = timeit.Timer( textwrap.dedent( """ for s, i in l: d.setdefault(s,i) """), setup_statement, ) show_results(t.timeit(number=count)) # 如果查找现有值时产生了一个KeyError异常,则这个方法会增加值。 # Using exceptions print('KeyError :',end=' ') t = timeit.Timer( textwrap.dedent( """ for s, i in l: try: existing = d[s] except KeyError: d[s] = i """), setup_statement, ) show_results(t.timeit(number=count)) # 最后一个方法使用"in"来确定字典是否有某个特定的值。 # Using "in" print('"not in" :',end=' ') t = timeit.Timer( textwrap.dedent( """ for s, i in l: if s not in d: d[s] = i """), setup_statement, ) show_results(t.timeit(number=count))

运行时,脚本会生成以下输出。


最新回复(0)