为什么删除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 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    对我来说,它们的速度几乎相同:(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。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看