过去,当我需要在紧密循环中进行类似数组的索引查找时,我通常使用元组,因为它们通常看起来非常高效(接近只使用 n 个变量)。然而,我今天决定质疑这个假设,并得出了一些令人惊讶的结果:
In [102]: l = range(1000)
In [103]: t = tuple(range(1000))
In [107]: timeit(lambda : l[500], number = 10000000)
Out[107]: 2.465047836303711
In [108]: timeit(lambda : t[500], number = 10000000)
Out[108]: 2.8896381855010986
元组查找似乎比列表查找花费 17% 的时间!重复的实验给出了类似的结果。拆开每个,我发现它们都是:
In [101]: dis.dis(lambda : l[5])
1 0 LOAD_GLOBAL 0 (l)
3 LOAD_CONST 1 (5)
6 BINARY_SUBSCR
7 RETURN_VALUE
作为参考,典型的 10,000,000 个全局变量查找/返回需要 2.2 秒。另外,我在没有 lambda 的情况下运行它,你知道,以防万一(请注意,数字 = 100,000,000 而不是 10,000,000)。
In [126]: timeit('t[500]', 't=range(1000)', number=100000000)
Out[126]: 6.972800970077515
In [127]: timeit('t[500]', 't=tuple(range(1000))', number=100000000)
Out[127]: 9.411366939544678
在这里,元组查找需要 35% 的时间。这里发生了什么?对于非常紧凑的循环,这实际上似乎是一个显着的差异。这可能是什么原因造成的?
请注意,对于分解为变量(例如 x,y=t),元组稍微快一些(在我的几次测试中减少了约 6% 的时间),对于从固定数量的参数进行构造,元组更快(减少了约 83% 的时间) )。不要将这些结果作为一般规则;我刚刚执行了一些对大多数项目来说毫无意义的小测试。
In [169]: print(sys.version)
2.7.1 (r271:86882M, Nov 30 2010, 09:39:13)
[GCC 4.0.1 (Apple Inc. build 5494)]