为什么删除else会使我的代码变慢?
发布于 2021-01-29 17:58:26
考虑以下功能:
def fact1(n):
if n < 2:
return 1
else:
return n * fact1(n-1)
def fact2(n):
if n < 2:
return 1
return n * fact2(n-1)
它们应该是等效的。但是存在性能差异:
>>> T(lambda : fact1(1)).repeat(number=10000000)
[2.5754408836364746, 2.5710129737854004, 2.5678811073303223]
>>> T(lambda : fact2(1)).repeat(number=10000000)
[2.8432059288024902, 2.834425926208496, 2.8364310264587402]
不带的版本else慢10%。这非常重要。为什么?
关注者
0
被浏览
48
1 个回答
-
对我来说,它们的速度几乎相同:(Debian上的Python 2.6.6)
In [4]: %timeit fact1(1) 10000000 loops, best of 3: 151 ns per loop In [5]: %timeit fact2(1) 10000000 loops, best of 3: 154 ns per loop
字节码也非常相似:
In [6]: dis.dis(fact1) 2 0 LOAD_FAST 0 (n) 3 LOAD_CONST 1 (2) 6 COMPARE_OP 0 (<) 9 JUMP_IF_FALSE 5 (to 17) 12 POP_TOP 3 13 LOAD_CONST 2 (1) 16 RETURN_VALUE >> 17 POP_TOP 5 18 LOAD_FAST 0 (n) 21 LOAD_GLOBAL 0 (fact) 24 LOAD_FAST 0 (n) 27 LOAD_CONST 2 (1) 30 BINARY_SUBTRACT 31 CALL_FUNCTION 1 34 BINARY_MULTIPLY 35 RETURN_VALUE 36 LOAD_CONST 0 (None) 39 RETURN_VALUE In [7]: dis.dis(fact2) 2 0 LOAD_FAST 0 (n) 3 LOAD_CONST 1 (2) 6 COMPARE_OP 0 (<) 9 JUMP_IF_FALSE 5 (to 17) 12 POP_TOP 3 13 LOAD_CONST 2 (1) 16 RETURN_VALUE >> 17 POP_TOP 4 18 LOAD_FAST 0 (n) 21 LOAD_GLOBAL 0 (fact) 24 LOAD_FAST 0 (n) 27 LOAD_CONST 2 (1) 30 BINARY_SUBTRACT 31 CALL_FUNCTION 1 34 BINARY_MULTIPLY 35 RETURN_VALUE
唯一的区别是,如果控制到达函数主体的末尾,则else返回包含代码的版本None。