我在给自己做基准的时候,遇到了这个有趣的事情。我想获取一个字典的前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)
Prints:
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})
注释显示了我在运行同一代码3次后得到的时间。正如你所看到的,即使执行大量的重复,也有可能获得相当大的测量时间变化。这可能是由于几种不同的事情。
正如 @Andrej Kesely 所说的,你的瓶颈是由于你把你的字典键投进了一个列表。通过这样做,Python 会检查整个 dictionary keys,因为这就是它如何将某些东西转换为一个 list
一般来说,。因此,避免这种情况的发生,可以得到更好的效果。