파이썬에서 반복자가 예외를 발생시키는 이유는 무엇입니까?


48

Java 반복자 구문은 다음과 같습니다 (C #에서 비슷한 구문).

Iterator it = sequence.iterator();

while (it.hasNext()) {
    System.out.println(it.next());
}

말이됩니다. 다음은 파이썬에서 동등한 구문입니다.

it = iter(sequence)
while True:
    try:
        value = it.next() 
    except StopIteration:
        break
    print(value)

예외는 예외적 인 상황에서만 사용해야한다고 생각했습니다.

파이썬이 예외를 사용하여 반복을 중지하는 이유는 무엇입니까?


답변:


51

에 대한 try-except 블록을 명시 적으로 작성하지 않고 해당 표현식을 작성하는 매우 파이썬적인 방법이 있습니다 StopIteration.

# some_iterable is some collection that can be iterated over
# e.g., a list, sequence, dict, set, itertools.combination(...)

for value in some_iterable:
    print(value)

소개 된 이유 와 반복자 뒤에있는 논리 에 대해 더 자세히 알고 싶다면 관련 PEP 234 255를 읽으십시오 StopIteration.

파이썬의 일반적인 원칙은 파이썬 방법이 만족하는 무언가를 수행하는 한 가지 방법 ( import this)을, 바람직하게는 아름답고 명시 적이며 읽기 쉽고 단순하게하는 것입니다. 파이썬은 반복자에게 hasNext멤버 함수를 제공하지 않기 때문에 동등한 코드가 필요 합니다. 사람들이 반복자를 직접 반복하는 것을 선호합니다 (그리고 그것을 읽고 예외를 잡기 위해 다른 것을 해야하는 경우).

StopIteration이터레이터 끝에서 예외를 자동으로 잡는 것은 의미가 있으며 EOFError파일 끝을지나 읽은 경우 발생 하는 것과 유사 합니다.


6
"Pythonic"방식은 "iter (sequence) :"의 값보다는 "순서의 값 :"과 훨씬 비슷해 보입니다. 게시물 업데이트?
얌 마르코비치

15
@ 얌 : 동의합니다. 기존의 시퀀스를 가져 와서 for 루프를 적용하기 위해 반복자로 변환하는 것은 pythonic이 아닙니다. 시퀀스는 이미 반복 가능하므로 a list에서 a 로의 변환은 의미 listiterator가 없습니다. 나는 어떻게해야 같은 방법 반복자, 돌이 당신이해야 어떤 반복 가능한 돌이 (설명, NullUserException의 시작 지점을 따라 첫 번째 라인을 유지 list, set, str, tuple, dict, file, generator, 등). it = itertools.combinations("ABCDE", 2)의미있는 반복자의 더 나은 예를 얻는 것과 같은 일을 할 수있었습니다 .
dr jimbob 님이

1
it = iter(sequence)필요하지 않습니다.
Caridorc

2
@Caridorc-의견을 읽으면 요점을 알 수 있습니다. 질문의 시작점 (명시 적으로 질문 한 위치 iterators)을 따르지 않아도 iter되며 iterator(try type([])( list) vs type(iter([]))( listiterator)) 를 명시 적으로 생성 해야 합니다 .
dr jimbob

//, @drjimbob,이 질문에 대한 두 번째 주석에서 훌륭한 지적을합니다. 나는 iterables의 고급 기능에 약간 익숙하며 주석을 읽지 않았다면 그것을 잡지 못했을 것입니다. 질문 자체가 답변 의 첫 번째 주요 부분 인 "파이썬 웨이 (Python Way)" 로 어떻게 변할 수 있는지에 대한 요점을 볼 수 있다면 우리 자신이 빈약 한 자기 교육 영혼에게 도움이 될 것이라고 생각합니다 .
Nathan Basanese

29

파이썬이 예외를 사용하여 반복을 중지하는 이유는 PEP 234에 설명되어 있습니다 .

반복의 끝을 알리는 예외가 너무 비싸지 않은지 의문이 제기되었습니다. StopIteration 예외에 대한 몇 가지 대안이 제안되었습니다 : 종료를 알리는 특수 값 End, 반복기 완료 여부를 테스트하는 end () 함수, IndexError 예외 재사용.

  • 특별한 값은 시퀀스가 ​​그 특별한 값을 포함한다면, 그 시퀀스에 대한 루프는 경고없이 조기에 끝나는 문제가 있습니다. null로 끝나는 C 문자열에 대한 경험으로 인해 이것이 발생할 수있는 문제를 가르쳐주지 못했다면, 특수한 End 값이 이름으로!

  • end () 함수를 호출하면 반복 당 두 번의 호출이 필요합니다. 두 번의 호출은 한 번의 호출보다 예외가 더 많은 테스트보다 훨씬 비쌉니다. 특히 시간이 중요한 for 루프는 예외적으로 매우 저렴하게 테스트 할 수 있습니다.

  • IndexError를 재사용하면 루프를 조기에 종료하여 마스킹되는 실제 오류 일 수 있으므로 혼동을 일으킬 수 있습니다.

참고 : 시퀀스를 반복하는 관용적 파이썬 방법은 다음과 같습니다.

for value in sequence:
    print (value)

21

철학의 차이입니다. Pythonic 디자인 철학은 EAFP입니다 .

허가보다 용서를 구하는 것이 더 쉽습니다. 이 일반적인 Python 코딩 스타일은 유효한 키 또는 속성이 있다고 가정하고 가정이 거짓으로 판명되면 예외를 포착합니다. 이 깨끗하고 빠른 스타일은 많은 사람들의 존재에 의해 특징 tryexcept문. 이 기술 은 C와 같은 다른 많은 언어에 공통적 인 LBYL 스타일 과 대조됩니다 .


7

Java 구현에는 hasNext()메소드 가 있으므로을 수행하기 전에 빈 반복기를 확인할 수 있습니다 next(). next()요소가없는 Java 반복자를 호출하면 a NoSuchElementException가 발생 합니다.

따라서 효과적으로 파이썬에서 try..except와 같이 Java에서 try..catch를 수행 할 수 있습니다. 그리고 예, 이전 답변에 따르면, 철학은 파이썬 세계에서 매우 중요합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.