[python] 왜 파이썬은 for 및 while 루프 후에 ‘else’를 사용합니까?

이 구문이 어떻게 작동하는지 이해합니다.

for i in range(10):
    print(i)

    if i == 9:
        print("Too big - I'm giving up!")
        break;
else:
    print("Completed successfully")

그러나 왜 else키워드가 키워드로 사용 되는지 이해하지 못합니다 . for블록이 완료되지 않은 경우에만 문제의 코드가 실행됨을 나타냅니다 . 내가 어떻게 생각하든 내 두뇌는 for성명서에서 else블록으로 완벽하게 진행될 수 없습니다 . 나에게 continue또는 continuewith더 이해가 될 것입니다 (그리고 나는 그것을 읽도록 훈련하려고합니다).

파이썬 코더가 어떻게이 구조를 머리에서 (또는 원하는 경우 큰 소리로) 읽는지 궁금합니다. 아마도 그러한 코드 블록을 더 쉽게 해독 할 수있는 것을 놓치고 있습니까?



답변

노련한 파이썬 코더조차도 이상한 구성입니다. for-loops와 함께 사용하면 기본적으로 “반복 가능한 항목을 찾으십시오. 에서처럼 :

found_obj = None
for obj in objects:
    if obj.key == search_key:
        found_obj = obj
        break
else:
    print('No object found.')

그러나이 구문을 볼 때마다 더 나은 대안은 검색을 함수로 캡슐화하는 것입니다.

def find_obj(search_key):
    for obj in objects:
        if obj.key == search_key:
            return obj

또는 목록 이해력을 사용하십시오.

matching_objs = [o for o in objects if o.key == search_key]
if matching_objs:
    print('Found {}'.format(matching_objs[0]))
else:
    print('No object found.')

의미 적으로 다른 두 버전과 동일하지는 않지만 전체 목록을 반복하는지 여부와 상관없이 성능이 중요하지 않은 코드에서는 충분히 잘 작동합니다. 다른 사람들은 동의하지 않을 수도 있지만 개인적으로 프로덕션 코드에서 for-else 또는 while-else 블록을 사용하지 않는 것이 좋습니다.

[Python-ideas] for … else 스레드 요약 참조


답변

일반적인 구성은 무언가를 찾을 때까지 루프를 실행 한 다음 루프를 벗어나는 것입니다. 문제는 루프에서 벗어나거나 루프가 종료되면 어떤 사건이 발생했는지 확인해야한다는 것입니다. 한 가지 방법은 플래그 또는 저장 변수를 작성하여 루프가 어떻게 종료되었는지 확인하기 위해 두 번째 테스트를 수행하는 것입니다.

예를 들어 목록을 검색하고 플래그 항목을 찾을 때까지 각 항목을 처리 한 다음 처리를 중지해야한다고 가정하십시오. 플래그 항목이 없으면 예외를 발생시켜야합니다.

파이썬을 사용하면 forelse당신이 구성

for i in mylist:
    if i == theflag:
        break
    process(i)
else:
    raise ValueError("List argument missing terminal flag.")

이 구문 설탕을 사용하지 않는 방법과 이것을 비교하십시오.

flagfound = False
for i in mylist:
    if i == theflag:
        flagfound = True
        break
    process(i)

if not flagfound:
    raise ValueError("List argument missing terminal flag.")

첫 번째 경우에는 raisefor 루프와 밀접하게 바인딩됩니다. 두 번째로 바인딩이 강력하지 않고 유지 관리 중에 오류가 발생할 수 있습니다.


답변

Raymond Hettinger는 Transforming Code를 Beautiful, Idiomatic Python으로 변환 하는 훌륭한 프레젠테이션을 통해 작문 의 역사를 간단히 설명합니다 for ... else. 관련 섹션은 15:50에서 시작하여 약 3 분 동안 계속되는 “루프에서 여러 개의 종료점 구별” 입니다. 요점은 다음과 같습니다.

  • for ... else구조는 특정 GOTO사용 사례를 대체하기 위해 Donald Knuth에 의해 고안되었습니다 .
  • 재사용 else키워드 만든 의미가 있기 때문 “해당 시간, 크 누스 사용, 사람들이 알고있는 것을있어, 모든 [ for문]은 내장했다 ifGOTO아래, 그들은 예상 else;”
  • 뒤늦은 통찰력은 “휴식 없음”(또는 아마도 “휴식 없음”)으로 불리어야하는데 혼란스럽지 않을 것입니다. *

질문이 “왜이 키워드를 바꾸지 않습니까?” 그러면 Cat Plus Plus가 가장 정확한 답을 제공했을 것입니다 .이 시점에서 기존 코드를 구현하기에는 너무 파괴적입니다. 그러나 당신이 정말로 묻는 질문이 else처음부터 재사용 된 이유라면 , 아마도 당시에는 좋은 생각처럼 보였습니다.

개인적으로, 나는 루프 내부에 속하는 것으로 한눈에 오해 할 수있는 # no break곳이라면 어디에서나 인라인 으로 주석을다는 것을 좋아합니다 else. 합리적으로 명확하고 간결합니다. 이 옵션은 Bjorn 이 그의 답변 끝에서 링크 한 요약 에서 간단히 언급 합니다 .

완성도를 높이기 위해 구문을 약간 변경하면이 구문을 원하는 프로그래머는 지금 구문을 사용할 수 있습니다.

for item in sequence:
    process(item)
else:  # no break
    suite

* 비디오의 해당 부분에서 인용 한 인용문 : “람다 makefunction 을 호출 한 것처럼 아무도 ‘람다는 무엇을합니까?’


답변

언어에 새로운 키워드를 도입하고 싶지 않았기 때문입니다. 각각은 식별자를 훔치고 이전 버전과의 호환성 문제를 유발하므로 일반적으로 최후의 수단입니다.


답변

간단하게하기 위해 그렇게 생각할 수 있습니다.

  • 루프 에서 break명령 이 발생하면 부품이 호출되지 않습니다.forelse
  • 루프 에서 break명령이 발생하지 않으면 부품이 호출됩니다.forelse

다시 말해, for 루프 반복이로 “깨지지 않은” break경우 else파트가 호출됩니다.


답변

for / else가 무엇을했는지 ‘가져올’수있는 가장 쉬운 방법은 더 중요하게 그것을 사용할 때 break statement가 어디로 향하는 지에 집중하는 것이 었습니다. For / else 구문은 단일 블록입니다. 브레이크는 블록 밖으로 점프하므로 else 절을 ​​’오버’합니다. else 절의 내용이 단순히 for 절 뒤에 올 경우 절대로 건너 뛰지 않으므로 if에 넣으면 동등한 논리를 제공해야합니다. 이것은 이전에 언급되었지만,이 말에서는 그다지 알려지지 않았으므로 다른 사람에게 도움이 될 수 있습니다. 다음 코드 조각을 실행하십시오. 나는 명확성을 위해 ‘휴식 없음’이라는 의견에 진심으로 찬성한다.

for a in range(3):
    print(a)
    if a==4: # change value to force break or not
        break
else: #no break  +10 for whoever thought of this decoration
    print('for completed OK')

print('statement after for loop')


답변

나는 문서의 큰 설명이 있다고 생각 다른 사람을 , 계속

[…] 루프가 목록의 소진을 통해 종료 될 때 (with) 또는 조건이 false가되는 동안 (with가있는 경우) 실행되지만 break 문으로 루프가 종료 될 때는 실행되지 않습니다. “

출처 : Python 2 Docs : 제어 흐름에 대한 자습서