为什么`if`在语句之前检查比在语句之后检查要快得多?

时间:2015-04-28 23:05:26

标签: python performance python-3.x performance-testing

这是我的意思的一个例子:

s = """
if x > 10:
    x -= 10
else:
    x = 0
"""
import timeit
print(timeit.timeit(s, setup="x=5", number=99999999))

在我的计算机上输出大约3秒钟,无论设置如何(x=5 vs x=15,没有区别)

如果我要使用更短的代码,首先减少代码x -= 10然后再检查x < 0,我会得到更糟糕的结果:

s = """
x -= 10
if x < 0:
    x = 0
"""
import timeit
print(timeit.timeit(s, setup="x=5", number=99999999))

无论x的初始值是5还是15,它都会输出大约6秒钟。

我知道x < 10会慢一些,因为我们先拨打x -= 10,然后设置x = 0,而不是简单地设置x一次。

问题是,99%的时间我程序中x的初始值被设置为远高于10的数字,所以我认为我会使用较短的版本,因为大部分时间我认为性能没有区别。

然而,即使x > 10,性能也存在巨大差异,为什么会这样?

2 个答案:

答案 0 :(得分:7)

你的前提是错的。 setup仅对整个timeit运行一次。如果您确保x高于10,则症状会消失:

>>> s1 = """
... if x > 10:
...     x -= 10
... else:
...     x = 0
... """
>>> s2 = """
... x -= 10
... if x < 0:
...     x = 0
... """
>>> import timeit
>>> print(timeit.timeit(s1, setup="x=1000000000", number=99999999))
8.934118068675566
>>> print(timeit.timeit(s2, setup="x=1000000000", number=99999999))
8.744505329313448

答案 1 :(得分:-2)

更新:这是错误的;把它留作没有导致行为的记录

至少在某种程度上,这可能是代码在timeit.timeit下运行的方式。你可以通过计算一段代码来测试这个:

x = 5
for i in xrange(99999999):
  x -= 10
  if x < 0:
    x = 0

对于第二种情况,并将该时间与第一种情况的类似重写进行比较。