[python] except 절에서`or`를 사용하면 왜 SyntaxError가 발생하지 않습니까? 올바른 사용법이 있습니까?

직장에서 나는 연산자 except와 절을 우연히 발견했습니다 or.

try:
    # Do something.
except IndexError or KeyError:
    # ErrorHandling

예외 클래스가 튜플로 전달되어야한다는 것을 알고 있지만 SyntaxError.

그래서 먼저 실제로 작동하는지 조사하고 싶었습니다. 그리고 그렇지 않습니다.

>>> def with_or_raise(exc):
...     try:
...         raise exc()
...     except IndexError or KeyError:
...         print('Got ya!')
...

>>> with_or_raise(IndexError)
Got ya!

>>> with_or_raise(KeyError)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in with_or_raise
KeyError

따라서 두 번째 예외를 포착하지 않았고 바이트 코드를 살펴보면 이유가 더 분명해집니다.

>>> import dis
>>> dis.dis(with_or_raise)
  2           0 SETUP_EXCEPT            10 (to 12)

  3           2 LOAD_FAST                0 (exc)
              4 CALL_FUNCTION            0
              6 RAISE_VARARGS            1
              8 POP_BLOCK
             10 JUMP_FORWARD            32 (to 44)

  4     >>   12 DUP_TOP
             14 LOAD_GLOBAL              0 (IndexError)
             16 JUMP_IF_TRUE_OR_POP     20
             18 LOAD_GLOBAL              1 (KeyError)
        >>   20 COMPARE_OP              10 (exception match)
             22 POP_JUMP_IF_FALSE       42
             24 POP_TOP
             26 POP_TOP
             28 POP_TOP

  5          30 LOAD_GLOBAL              2 (print)
             32 LOAD_CONST               1 ('Got ya!')
             34 CALL_FUNCTION            1
             36 POP_TOP
             38 POP_EXCEPT
             40 JUMP_FORWARD             2 (to 44)
        >>   42 END_FINALLY
        >>   44 LOAD_CONST               0 (None)
             46 RETURN_VALUE

보시다시피 명령어 14는 먼저 IndexError클래스를 스택에 로드합니다 . 그런 다음 그 값이 True, 파이썬 진실성 때문 인지 확인 하고 마지막으로 명령 20으로 바로 이동 exception match합니다. 명령 18을 건너 뛰었 KeyError으므로 스택에로드되지 않았으므로 일치하지 않습니다.

Python 2.7 및 3.6으로 동일한 결과를 시도했습니다.

그렇다면 왜 유효한 구문입니까? 나는 그것이 다음 중 하나라고 상상합니다.

  1. 정말 오래된 버전의 파이썬에서 나온 인공물입니다.
  2. 실제로 orexcept조항 내에서 사용하기위한 유효한 사용 사례 가 있습니다.
  3. except키워드 뒤에 식을 허용해야 할 수도있는 Python 파서의 제한 사항입니다 .

내 투표는 3에 있습니다 (파이썬의 새로운 파서에 대한 토론을 보았지만) 누군가 그 가설을 확인할 수 있기를 바랍니다. 예를 들어 2 인 경우 해당 사용 사례를 알고 싶습니다.

또한, 나는 그 탐사를 어떻게 계속할 것인지에 대해 약간의 실마리가됩니다. CPython 파서의 소스 코드를 파헤쳐 야하지만 idk를 어디서 찾을 수 있고 더 쉬운 방법이 있습니까?



답변

에서는 except e, e유효한 파이썬 표현식이 될 수 있습니다 :

try1_stmt ::=  "try" ":" suite
               ("except" [expression ["as" identifier]] ":" suite)+
               ...

[..] except식이 있는 절의 경우 해당식이 평가되고 결과 개체가 예외와“호환”할 경우 해당 절이 예외와 일치합니다. 예외 개체의 클래스 또는 기본 클래스이거나 예외와 호환되는 항목이 포함 된 튜플 인 경우 개체는 예외와 호환됩니다.

https://docs.python.org/3/reference/compound_stmts.html#the-try-statement

표현식 IndexError or KeyError은 값을 산출합니다 IndexError. 따라서 이것은 다음과 같습니다.

except IndexError:
   ...


답변

논리적 표현식 대신 첫 번째 유형의 거짓 요소를 반환하는 대신 n- 튜플 유형을 사용해야합니다.

def with_or_raise(exc):
  try:
    raise exc()
  except (IndexError,KeyError):
    print('Got ya!')


답변