关于python:len(List)的性能与读取变量

perfomance of len(List) vs reading a variable

类似的问题已经在这里询问len()函数的Cost。 但是,此问题着眼于len自身的代价。
假设我有一个重复多次len(List)的代码,每次都是O(1),读取变量也是O(1),加上赋值也是O(1)

作为附带说明,我发现n_files = len(Files)在代码中比重复的len(Files)更具可读性。 因此,这已经成为我这样做的动力。
您还可以反对我,可以修改代码Files中的某处,因此n_files不再正确,但事实并非如此。

我的问题是:
len(Files)的呼叫次数,之后访问n_files
会更快吗?


一些结果(一百万次呼叫的时间,以秒为单位),在Windows 7上使用Python 2.7.10列出了十个元素; store是我们存储长度还是继续调用len,而alias是我们是否为len创建本地别名:

1
2
3
4
5
Store Alias n=      1      10     100
Yes   Yes       0.862   1.379   6.669
Yes   No        0.792   1.337   6.543
No    Yes       0.914   1.924  11.616
No    No        0.879   1.987  12.617

和一千个元素列表:

1
2
3
4
5
Store Alias n=      1      10     100
Yes   Yes       0.877   1.369   6.661
Yes   No        0.785   1.299   6.808
No    Yes       0.926   1.886  11.720
No    No        0.891   1.948  12.843

结论:

  • 存储结果比重复调用len更有效,即使对于n == 1而言也是如此。
  • len创建本地别名可以对较大的n进行较小的改进,在较大的n中,我们不存储结果,但不如存储结果那样多。和
  • 列表长度的影响可以忽略不计,这表明是否对整数进行插值没有任何区别。

测试脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def test(n, l, store, alias):
    if alias:
        len_ = len
        len_l = len_(l)
    else:
        len_l = len(l)
    for _ in range(n):
        if store:
            _ = len_l
        elif alias:
            _ = len_(l)
        else:
            _ = len(l)

if __name__ == '__main__':
    from itertools import product
    from timeit import timeit
    setup = 'from __main__ import test, l'
    for n, l, store, alias in product(
        (1, 10, 100),
        ([None]*10,),
        (True, False),
        (True, False),
    ):
        test_case = 'test({!r}, l, {!r}, {!r})'.format(n, store, alias)
        print test_case, len(l),
        print timeit(test_case, setup=setup)

在python中进行函数调用的代价很高,因此,如果您100%确信从变量访问n_files的长度时,其大小不会改变,则可以使用该变量,如果那样的话,您更容易理解。好。

访问len(list)和从变量访问的性能测试示例给出以下结果-

1
2
3
4
5
6
7
8
9
In [36]: l = list(range(100000))

In [37]: n_l = len(l)

In [40]: %timeit newn = len(l)
10000000 loops, best of 3: 92.8 ns per loop

In [41]: %timeit new_n = n_l
10000000 loops, best of 3: 33.1 ns per loop

访问变量总是比使用len()更快。


使用len(Files)代替n_files可能会更慢。是的,您必须查找n_files,但是在前一种情况下,您必须同时查找lenFiles,然后在该调用之上调用"计算"?? Files长度的函数。


使用l = len(li)更快:

1
2
3
4
5
python -m timeit -s"li = [1, 2, 3]""len(li)"
1000000 loops, best of 3: 0.239 usec per loop

python -m timeit -s"li = [1, 2, 3]; l = len(li)""l"
10000000 loops, best of 3: 0.0949 usec per loop