리스트 컴프리헨션에서 예외를 직접 처리할 수 없는 이유
파이썬에는 예외를 처리하거나 무시하는 기능을 제공하는 내장 함수가 없습니다. 따라서 리스트 컴프리헨션(list comprehension) 안에서 발생하는 모든 예외를 직접 처리하는 것은 불가능합니다.
그 이유는 리스트 컴프리헨션이 하나 이상의 표현식(expression)으로만 구성될 수 있기 때문입니다. 파이썬에서 예외를 잡거나 무시하거나 처리하는 try~except 구문은 오직 문(statement) 수준에서만 사용할 수 있습니다.
이런 제약을 우회하는 대표적인 방법은 두 가지입니다.
- 예외가 발생하기 쉬운 하위 표현식의 평가를 별도의 함수에 위임하고, 그 함수 내부에서 try~except로 처리한다.
- 컴프리헨션을 실행하기 전에 예외를 일으킬 가능성이 있는 값을 미리 검사·필터링한다.
방법 1: try~except 문으로 감싸기
리스트 컴프리헨션 전체를 try~except 블록으로 감싸면, 컴프리헨션 실행 중 발생한 예외를 문 단위에서 처리할 수 있습니다.
foo = (5, 7, 1, 0, 9)
def bar(numbers):
try:
return [1 / i for i in numbers]
except ZeroDivisionError as e:
print(e)
bar(foo)튜플 (5, 7, 1, 0, 9)에는 0이 포함되어 있어 1/0을 계산하는 순간 ZeroDivisionError가 발생하고, except 블록이 이를 받아 에러 메시지를 출력합니다.
실행 결과
division by zero Process finished with exit code 0
방법 2: if 조건으로 0 값을 사전에 제외하기
발생한 예외를 처리하는 대신, 애초에 예외를 일으킬 수 있는 값을 결과에서 제외하는 방법도 있습니다. if 절을 활용하면 0인 요소를 건너뛰고 나머지 값만으로 안전하게 리스트를 생성할 수 있습니다.
foo = (5, 7, 1, 0, 9) result = [1 / i for i in foo if i != 0] print(result)
실행 결과
[0.2, 0.14285714285714285, 1.0, 0.1111111111111111]
정리
리스트 컴프리헨션 내부에서는 try~except를 사용할 수 없으므로, ① 컴프리헨션을 포함한 함수 전체를 try~except로 감싸 예외를 처리하거나, ② if 조건으로 위험한 값을 미리 제외하는 방식으로 예외 상황을 다루는 것이 바람직합니다.