【发布时间】:2021-11-04 11:10:48
【问题描述】:
我最近询问了the fastest way to create powers of ten,结果发现最快的方法实际上有点像sneaky workaround,您首先创建所有可能的值,然后在需要时简单地查找它们。
在解决方案中,list 用作查找表,但是,我刚刚了解到dicts should be much faster 在查找操作方面(参见例如here)。但是当我尝试使用dict 作为查找表时,过程实际上更慢:
n = 200
18 ns 18 ns 18 ns f[n] # list
22 ns 22 ns 22 ns g[n] # dict
n = -200
18 ns 18 ns 18 ns f[n] # list
29 ns 29 ns 29 ns g[n] # dict
这是为什么呢?这是否与keys 是整数而不是字符串这一事实有关? (另外我猜sets不能用在这种情况下?)
这是我运行的代码:
from timeit import repeat
solutions = [
'f[n] # list',
'g[n] # dict',
]
for n in 200, -200:
print(f'n = {n}')
setup = f'''
n = {n}
f = [10.0 ** i for i in [*range(309), *range(-323, 0)]]
g = {{i: 10.0 ** i for i in range(-323, 309)}}
'''
for solution in solutions:
try:
ts = sorted(repeat(solution, setup, repeat=50))[:3]
except OverflowError:
ts = [None] * 3
print(
*('%3d ns ' % (t * 1e3) if t else ' error ' for t in ts), solution
)
print()
【问题讨论】:
-
对我来说,有趣的是 dict 对于负值变得明显变慢,而列表不受此影响。如果您将
hash(n)添加到测试的表达式中,您可能会发现对于负值也变得慢得多。还不知道为什么。 -
@KellyBundy 我认为这可能是由于 Python 缓存了小整数(在 -1 到 256 之类的范围内,IIRC)。必须将超出此范围的整数创建为新的 GC 对象。索引相同而不是仅仅相等的键稍微快一些,我想如果索引是唯一执行的操作,那么这种差异实际上可能相当显着。
-
嗯,其实只有
hash函数好像受影响,not dict access。 -
@Jasmijn Argh,在我的 PC 上使用完整的 dict 测试整个范围
for n in range(-323, 309):(这样我可以运行更长时间)似乎再次受到 [-5, 256] 范围的影响。对于范围 [-323,-6],我得到非常一致的 137 ns,然后对于 [-5,0] 是 109 ns,除了 -1 的 183 ns,然后是 [1,256] 的 108 ns,然后是 [257,308] 的 136 ns。
标签: python list dictionary lookup