【发布时间】:2015-12-01 07:31:35
【问题描述】:
从this page,我们知道:
链式比较比使用
and运算符更快。 写x < y < z而不是x < y and y < z。
但是,我在测试以下代码 sn-ps 时得到了不同的结果:
$ python -m timeit "x = 1.2" "y = 1.3" "z = 1.8" "x < y < z"
1000000 loops, best of 3: 0.322 usec per loop
$ python -m timeit "x = 1.2" "y = 1.3" "z = 1.8" "x < y and y < z"
1000000 loops, best of 3: 0.22 usec per loop
$ python -m timeit "x = 1.2" "y = 1.3" "z = 1.1" "x < y < z"
1000000 loops, best of 3: 0.279 usec per loop
$ python -m timeit "x = 1.2" "y = 1.3" "z = 1.1" "x < y and y < z"
1000000 loops, best of 3: 0.215 usec per loop
似乎x < y and y < z 比x < y < z 快。 为什么?
在这个网站上搜索了一些帖子(如this one)后,我知道“只评估一次”是x < y < z 的关键,但我仍然感到困惑。为了进一步研究,我使用dis.dis对这两个函数进行了反汇编:
import dis
def chained_compare():
x = 1.2
y = 1.3
z = 1.1
x < y < z
def and_compare():
x = 1.2
y = 1.3
z = 1.1
x < y and y < z
dis.dis(chained_compare)
dis.dis(and_compare)
输出是:
## chained_compare ##
4 0 LOAD_CONST 1 (1.2)
3 STORE_FAST 0 (x)
5 6 LOAD_CONST 2 (1.3)
9 STORE_FAST 1 (y)
6 12 LOAD_CONST 3 (1.1)
15 STORE_FAST 2 (z)
7 18 LOAD_FAST 0 (x)
21 LOAD_FAST 1 (y)
24 DUP_TOP
25 ROT_THREE
26 COMPARE_OP 0 (<)
29 JUMP_IF_FALSE_OR_POP 41
32 LOAD_FAST 2 (z)
35 COMPARE_OP 0 (<)
38 JUMP_FORWARD 2 (to 43)
>> 41 ROT_TWO
42 POP_TOP
>> 43 POP_TOP
44 LOAD_CONST 0 (None)
47 RETURN_VALUE
## and_compare ##
10 0 LOAD_CONST 1 (1.2)
3 STORE_FAST 0 (x)
11 6 LOAD_CONST 2 (1.3)
9 STORE_FAST 1 (y)
12 12 LOAD_CONST 3 (1.1)
15 STORE_FAST 2 (z)
13 18 LOAD_FAST 0 (x)
21 LOAD_FAST 1 (y)
24 COMPARE_OP 0 (<)
27 JUMP_IF_FALSE_OR_POP 39
30 LOAD_FAST 1 (y)
33 LOAD_FAST 2 (z)
36 COMPARE_OP 0 (<)
>> 39 POP_TOP
40 LOAD_CONST 0 (None)
似乎x < y and y < z 的反汇编命令比x < y < z 少。我应该考虑x < y and y < z 比x < y < z 快吗?
在 Intel(R) Xeon(R) CPU E5640 @ 2.67GHz 上使用 Python 2.7.6 进行测试。
【问题讨论】:
-
更多反汇编的命令并不意味着更复杂也不意味着更慢的代码。但是看到你的
timeit测试我对此很感兴趣。 -
当
y不仅仅是一个变量查找,而是一个更昂贵的过程(如函数调用)时,我假设与“评估一次”的速度差异出现了? IE。10 < max(range(100)) < 15比10 < max(range(100)) and max(range(100)) < 15快,因为两次比较都调用了一次max(range(100))。 -
@MarcoBonelli 它确实当反汇编代码 1) 不包含循环和 2) 每个字节码都非常快,因为此时主循环的开销变得很重要。
-
分支预测可能会弄乱您的测试。
-
@zehnpaard 我同意你的看法。当“y”不仅仅是一个简单的值(例如,函数调用或计算)时,我希望“y”在 x
标签: python performance