嵌套IF/ELSE和ELIF之间的区别?

Aus*_*art 2 python if-statement structure

这两个不同的代码组织之间是否存在语义或运行时差异?或者仅仅是简洁和空白的问题?

if something:
    ...
else:
    if other:
        ...
    else:
        ...
Run Code Online (Sandbox Code Playgroud)

比.

if something:
    ...
elif other:
    ...
else:
    ...
Run Code Online (Sandbox Code Playgroud)

wim*_*wim 6

没有逻辑差异.首选第二种方法,它更具可读性.

请注意,在抽象语法级别,它们完全等效:

>>> s1 = '''if something:
...     ...
... else:
...     if other:
...         ...
...     else:
...         ...'''
...         
>>> s2 = '''if something:
...     ...
... elif other:
...     ...
... else:
...     ...'''
...     
>>> ast.dump(ast.parse(s1)) == ast.dump(ast.parse(s2))
True
Run Code Online (Sandbox Code Playgroud)

具体来说,第二种形式转换为第一种形式:

>>> ast.dump(ast.parse(s2))
"Module(body=[If(test=Name(id='something', ctx=Load()), body=[Expr(value=Ellipsis())], orelse=[If(test=Name(id='other', ctx=Load()), body=[Expr(value=Ellipsis())], orelse=[Expr(value=Ellipsis())])])])"
>>> # pip install astdump
>>> astdump.indented(s2)
Module
  If
    Name
      Load
    Expr
      Ellipsis
    If
      Name
        Load
      Expr
        Ellipsis
      Expr
        Ellipsis
Run Code Online (Sandbox Code Playgroud)


ars*_*jii 5

两者都编译为相同的字节码(至少在CPython中):

>>> def a():
...     if something:
...         return 1
...     else:
...         if other:
...             return 2
...         else:
...             return 3
... 
>>> def b():
...     if something:
...         return 1
...     elif other:
...         return 2
...     else:
...         return 3
... 
>>> from dis import dis
>>> dis(a)
  2           0 LOAD_GLOBAL              0 (something)
              3 POP_JUMP_IF_FALSE       10

  3           6 LOAD_CONST               1 (1)
              9 RETURN_VALUE        

  5     >>   10 LOAD_GLOBAL              1 (other)
             13 POP_JUMP_IF_FALSE       20

  6          16 LOAD_CONST               2 (2)
             19 RETURN_VALUE        

  8     >>   20 LOAD_CONST               3 (3)
             23 RETURN_VALUE        
             24 LOAD_CONST               0 (None)
             27 RETURN_VALUE        
>>> dis(b)
  2           0 LOAD_GLOBAL              0 (something)
              3 POP_JUMP_IF_FALSE       10

  3           6 LOAD_CONST               1 (1)
              9 RETURN_VALUE        

  4     >>   10 LOAD_GLOBAL              1 (other)
             13 POP_JUMP_IF_FALSE       20

  5          16 LOAD_CONST               2 (2)
             19 RETURN_VALUE        

  7     >>   20 LOAD_CONST               3 (3)
             23 RETURN_VALUE        
             24 LOAD_CONST               0 (None)
             27 RETURN_VALUE        
Run Code Online (Sandbox Code Playgroud)

所以唯一的区别是源的可读性.正如其他人所说,第二种变体更清洁,应该是首选.

  • @wim尽管我认为这是挑剔,但我在回答中添加了一个注释,表明它实际上与CPython有关. (2认同)