[python] 목록 이해에서 예외를 처리하는 방법은 무엇입니까?

파이썬에서 각 반복이 예외를 던질 수있는 목록 이해력이 있습니다.

예를 들어 다음 과 같은 경우 :

eggs = (1,3,0,3,2)

[1/egg for egg in eggs]

ZeroDivisionError번째 요소에서 예외가 발생합니다.

이 예외를 처리하고 목록 이해를 계속 실행하려면 어떻게해야합니까?

내가 생각할 수있는 유일한 방법은 도우미 기능을 사용하는 것입니다.

def spam(egg):
    try:
        return 1/egg
    except ZeroDivisionError:
        # handle division by zero error
        # leave empty for now
        pass

그러나 이것은 나에게 약간 성가신 것 같습니다.

Python에서이 작업을 수행하는 더 좋은 방법이 있습니까?

참고 : 이것은 ( “를 참조 간단한 예입니다 예를 들어 내 진짜 예를 몇 가지 문맥을 필요로하기 때문에 내가 고안하는 것이 위의”). 0으로 나누는 오류를 피하는 데 관심이 없지만 목록 이해에서 예외를 처리하는 데 관심이 있습니다.



답변

파이썬에는 예외를 무시 (또는 예외의 경우 대체 값 & c 반환) 할 수있는 내장 표현식이 없으므로, 목록 이해가 표현식이므로 문자 그대로 “목록 이해에서 예외 처리”가 불가능합니다. 다른 표현을 포함하고 그 이상은 없습니다 (예 : 문이 없고 문만 예외를 포착 / 무시 / 처리 할 수 ​​있음).

함수 호출은 표현식이며 함수 본문은 원하는 모든 문을 포함 할 수 있으므로 예외가 발생하기 쉬운 하위 표현식의 평가를 함수에 위임하는 것이 가능한 해결 방법 중 하나입니다 (가능한 경우 다른 방법은 다음과 같습니다. 다른 답변에서도 제안 된 것처럼 예외를 유발할 수있는 값을 확인합니다.

“목록 이해에서 예외를 처리하는 방법”이라는 질문에 대한 정답은 모두이 모든 진실의 일부를 표현하는 것입니다. 1) 문자 그대로, 즉 이해 자체에서 어휘 적으로는 할 수 없습니다. 2) 실제로 작업을 함수에 위임하거나 가능한 경우 오류가 발생하기 쉬운 값을 확인합니다. 이것이 답이 아니라는 당신의 반복적 인 주장은 근거가 없습니다.


답변

나는이 질문이 꽤 오래되었다는 것을 알고 있지만, 이런 종류의 일을 더 쉽게하기 위해 일반적인 함수를 만들 수도 있습니다.

def catch(func, handle=lambda e : e, *args, **kwargs):
    try:
        return func(*args, **kwargs)
    except Exception as e:
        return handle(e)

그런 다음 당신의 이해에서 :

eggs = (1,3,0,3,2)
[catch(lambda : 1/egg) for egg in eggs]
[1, 0, ('integer division or modulo by zero'), 0, 0]

물론 기본 핸들 기능을 원하는대로 만들 수 있습니다 (기본적으로 ‘None’을 반환하는 대신).

이 질문이 귀하 또는 향후 시청자에게 도움이되기를 바랍니다.

참고 : 파이썬 3에서는 ‘handle’인수 키워드 만 만들고 인수 목록 끝에 넣습니다. 이것은 실제로 인수를 전달하는 것과 같은 것을 catch를 통해 훨씬 더 자연스럽게 만듭니다.


답변

당신이 사용할 수있는

[1/egg for egg in eggs if egg != 0]

이것은 단순히 0 인 요소를 건너 뜁니다.


답변

더 좋은 방법은 없습니다. 많은 경우에 Peter처럼 회피를 사용할 수 있습니다.

다른 옵션은 이해력을 사용하지 않는 것입니다

eggs = (1,3,0,3,2)

result=[]
for egg in eggs:
    try:
        result.append(egg/0)
    except ZeroDivisionError:
        # handle division by zero error
        # leave empty for now
        pass

그것이 더 성가 신지 아닌지를 결정하는 것은 당신에게 달려 있습니다.


답변

나는 초기 질문을하는 사람과 브라이언 헤드가 제안한 도우미 기능이 좋고 전혀 번거롭지 않다고 생각한다. 모든 작업을 수행하는 한 줄의 매직 코드가 항상 가능한 것은 아니므로 for루프 를 피하려는 경우 도우미 함수가 완벽한 솔루션 입니다. 그러나 나는 이것을 이것으로 수정할 것입니다.

# A modified version of the helper function by the Question starter 
def spam(egg):
    try:
        return 1/egg, None
    except ZeroDivisionError as err:
        # handle division by zero error        
        return None, err

출력은 this [(1/1, None), (1/3, None), (None, ZeroDivisionError), (1/3, None), (1/2, None)]입니다. 이 답변을 사용하면 원하는 방식으로 계속 진행할 수 있습니다.


답변

나는 이것을 언급하는 대답을 보지 못했습니다. 그러나이 예제는 알려진 실패 사례에 대해 예외가 발생하는 것을 방지하는 한 가지 방법입니다.

eggs = (1,3,0,3,2)
[1/egg if egg > 0 else None for egg in eggs]


Output: [1, 0, None, 0, 0]


답변