代码之家  ›  专栏  ›  技术社区  ›  no comment Pratyush Goutam

为什么“if x is None:pass”比单独使用“x is None”更快?

  •  0
  • no comment Pratyush Goutam  · 技术社区  · 2 年前

    Python 3.12中的计时结果(与不同机器上的3.11和3.13类似):

    When x = None:
    13.8 ns  x is None
    10.1 ns  if x is None: pass
    
    When x = True:
    13.9 ns  x is None
    11.1 ns  if x is None: pass
    
    Python: 3.12.0 (main, Oct  7 2023, 10:42:35) [GCC 13.2.1 20230801]
    

    怎么能做 更多 较少的 时间

    为什么 if x is None: pass 更快,当它必须做同样的事情时 x is None 检查,然后额外检查结果的真值(并执行或跳过 pass )?

    其他版本/机器上的时间:

    • Python 3.11:(12.4,9.3)和(12.0,8.8)
    • Python 3.13:(29.1,24.6)和(29.1、22.6)

    基准脚本( Attempt This Online! ):

    from timeit import repeat
    import sys
    
    for x in None, True:
        print(f'When {x = }:')
        for code in ['x is None', 'if x is None: pass'] * 2:
            t = min(repeat(code, f'{x=}', repeat=100))
            print(f'{t*1e3:4.1f} ns ', code)
        print()
    
    print('Python:', sys.version)
    
    1 回复  |  直到 2 年前
        1
  •  5
  •   deceze    2 年前

    查看拆解后的代码:

    >>> import dis
    >>> dis.dis('if x is None: pass')
      0           0 RESUME                   0
    
      1           2 LOAD_NAME                0 (x)
                  4 POP_JUMP_IF_NOT_NONE     1 (to 8)
                  6 RETURN_CONST             0 (None)
            >>    8 RETURN_CONST             0 (None)
    >>> dis.dis('x is None')
      0           0 RESUME                   0
    
      1           2 LOAD_NAME                0 (x)
                  4 LOAD_CONST               0 (None)
                  6 IS_OP                    0
                  8 RETURN_VALUE
    

    这个 if 箱子有特殊之处 POP_JUMP_IF_NOT_NONE 操作,比 LOAD_CONST IS_OP 。您可以在此处阅读有关它的详细讨论: https://github.com/faster-cpython/ideas/discussions/154 .