我在为自己做基准测试时遇到了这个有趣的事情。我正在尝试获取字典的前30个键,我已经写了三种方法来获取它,如下所示:
import time
dic = {str(i): i for i in range(10 ** 6)}
start_time = time.time()
x = list(dic.keys())[0:30]
print(time.time() - start_time)
start_time = time.time()
y = list(dic.keys())
x = y[0:30]
print(time.time() - start_time)
start_time = time.time()
z = dic.keys()
y = list(z)
x = y[0:30]
print(time.time() - start_time)
结果是:
0.015970945358276367
0.010970354080200195
0.01691460609436035
令人惊讶的是,第二种方法要快得多!对此有什么想法吗?
使用Python的timeit
模块来测量各种备选方案。我添加了我的,它不会将密钥转换为列表:
from timeit import timeit
dic = {str(i): i for i in range(10 ** 6)}
def f1():
x = list(dic.keys())[0:30]
return x
def f2():
y = list(dic.keys())
x = y[0:30]
return x
def f3():
z = dic.keys()
y = list(z)
x = y[0:30]
return x
def f4():
x = [k for _, k in zip(range(30), dic.keys())]
return x
t1 = timeit(lambda: f1(), number=10)
t2 = timeit(lambda: f2(), number=10)
t3 = timeit(lambda: f3(), number=10)
t4 = timeit(lambda: f4(), number=10)
print(t1)
print(t2)
print(t3)
print(t4)
打印:
0.1911074290110264
0.20418328599771485
0.18727918600779958
3.5186996683478355e-05
这可能是由于您对时间的测量不准确。你可以使用timeit
来做这类事情:
import timeit
dic = {str(i): i for i in range(10 ** 6)}
# 27.5125/29.0836/26.8525
timeit.timeit("x = list(dic.keys())[0:30]", number=1000, globals={"dic": dic})
# 28.6648/26.4684/30.9534
timeit.timeit("y = list(dic.keys());x=y[0:30]", number=1000)
# 31.7345/29.5301/30.7541
timeit.timeit("z=dic.keys();y=list(z);x=y[0:30]", number=1000, globals={'dic': dic})
注释显示了我在三次不同时间运行同一代码时得到的时间。正如你所看到的,即使进行大量的重复,也有可能获得相当大的测量时间变化。这可能是由于几个不同的原因:
- 项目可以在处理器的缓存中,也可以不在
- 您的处理器可能会忙于其他一些事情
- 等等
正如@Andrej Kesely所说,你的瓶颈是因为你把字典键放入了一个列表中。通过这样做,Python会遍历整个字典键,因为这就是它通常将某些内容转换为list
的方式。因此,通过避免这种情况,你可以得到更好的结果。