为什么Python的'all'功能如此之慢?

时间:2012-07-20 17:01:08

标签: python performance

我写了一些非常简单的测试(我知道,它们不是'结论',但它们让我很好奇)。我运行优化和所有爵士乐。

from time import time

alist = [ 2, 4, 6, 8, 10, 12, 24, 48, 64, 128 ]

def all_even( alist ):
    for val in alist:
        if not (val & 1) == 0:
            return False
    return True

def all_even_bad( alist ):
    result = False
    for val in alist:
        if not (val & 1) == 0:
            result = False
        else:
            result = True
    return result

def main():
    start = time()
    for i in range(1, 10000):
        all_even( alist )
    print('All even: {0}'.format(time() - start))

    start = time()
    for i in range(1, 10000):
        all_even_bad( alist )
    print('All even bad: {0}'.format(time() - start))


    start = time()
    for i in range(1, 10000):
        all( val & 1 == 0 for val in alist )
    print('All one: {0}'.format(time() - start))


if __name__ == '__main__':
    main()

我得到了结果:

> All even: 2.86299991608 
> All even bad: 3.71399998665 
> All one: 3.89900016785

看来内置功能不会提前纾困?

3 个答案:

答案 0 :(得分:7)

all()肯定会提前退出,我认为行为差异只是创建生成器所需开销的结果。

以下是all()提前退出的一些证明:

In [8]: alist = [3] + [0] * 2**20    # alist bigger, with an early odd

In [10]: %timeit all_even(alist)
1000000 loops, best of 3: 309 ns per loop

In [11]: %timeit all_even_bad(alist)
10 loops, best of 3: 133 ms per loop

In [12]: %timeit all(val & 1 == 0 for val in alist)
1000000 loops, best of 3: 891 ns per loop

请注意,即使此处all()all_even()慢,但它仍然明显快于未提前退出的函数版本。

答案 1 :(得分:2)

您没有因测试失败的元素,因此无法短路。

答案 2 :(得分:1)

由于列表中的所有数字实际上都是偶数,因此无法在逻辑上挽救早期? all()调用的开销可能来自构建generator对象。