为什么 Python 的“all"函数这么慢?
我写了一些非常简单的测试(我知道,它们不是决定性的",但它们让我很好奇).我运行优化和所有爵士乐.
I have wrote some very simple tests (I know, they are not 'conclusive', but they make me curious). I ran with optimization and all that jazz.
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
似乎内置函数没有提前退出?
It appears the built in function doesn't bail out early?
all()
确实会提前退出,我认为行为差异只是创建生成器所需开销的结果.
all()
definitely does exit early, I think the behavior difference is just the result of the overhead required to create the generator.
以下是 all()
确实提前退出的一些证据:
Here is some proof that all()
does exit early:
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()
慢,但它仍然比不提前退出的函数版本快得多.
Note that even though all()
is slower than all_even()
here, it is still significantly faster than the version of the function that doesn't exit early.