직장에서 나는 연산자 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으로 동일한 결과를 시도했습니다.
그렇다면 왜 유효한 구문입니까? 나는 그것이 다음 중 하나라고 상상합니다.
- 정말 오래된 버전의 파이썬에서 나온 인공물입니다.
- 실제로
or
는except
조항 내에서 사용하기위한 유효한 사용 사례 가 있습니다. 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!')