2.13. 루프 제어

두 가지 키워드가 루프의 동작 방식을 바꿉니다:

  • break – 루프를 즉시 빠져나갑니다.

  • continue – 현재 반복의 나머지 부분을 건너뛰고 다음 반복을 시작합니다.

둘 다 자신이 속한 가장 안쪽 루프에 적용됩니다.

2.13.1. break

조건이 충족되는 즉시 루프를 멈추려면 break 를 사용합니다. 전형적인 “검색 후 중지” 패턴은 다음과 같습니다:

found = None
for item in items:
    if matches(item):
        found = item
        break

if found is not None:
    print("found:", found)

while True: 루프에서는 break 가 루프를 끝내는 방법입니다:

while True:
    line = next_line()
    if line == "quit":
        break
    process(line)

2.13.2. continue

본문의 나머지 부분을 건너뛰고 다음 반복으로 넘어가려면 continue 를 사용합니다. 루프 안에서 항목을 걸러낼 때 유용합니다:

for n in numbers:
    if n < 0:
        continue            # skip negatives
    print(n)

같은 효과를 본문의 나머지 부분을 if 블록으로 감싸서 작성할 수도 있습니다. 유지 조건보다 건너뛰는 조건을 먼저 명시하기가 더 쉬울 때는 continue 가 더 명확할 때가 있습니다.

루프 안에서 continue 는 함수에서의 조기 return 과 같은 역할을 합니다. 즉, 처리하지 않는 경우들을 건너뛰고 주요 작업을 바깥쪽 들여쓰기에 평평하게 유지합니다. 걸러내고 처리하는 루프가 그 전형적인 형태입니다:

for item in items:
    if item is None:
        continue
    if not item.is_valid():
        continue
    process(item)

들여쓰기된 process(item) 줄이 실제 작업이며, 그 위의 각 가드는 어떤 항목이 건너뛰어지는지를 정확히 명시합니다.

2.13.3. 루프의 else

forwhile 모두 선택적인 else 블록을 받을 수 있습니다. 이 블록은 루프가 break 를 만나지 않고 완료될 때 실행됩니다. 가장 흔한 용도는 아무것도 찾지 못했을 때 대체 동작을 원하는 검색 루프입니다:

for item in items:
    if matches(item):
        print("found:", item)
        break
else:
    print("no match")

break 가 발동되면 else 블록은 건너뜁니다. 이 구조를 “for X in Y: …; 그리고-그렇지-않으면, 한 번도 빠져나오지 않았다면 Z를 한다”로 읽으십시오.

2.13.4. 흔한 루프 패턴

실제 스크립트에서 자주 등장하는 몇 가지 패턴이 있습니다:

  • 폴링(polling) – 진행하기 전에 어떤 조건이 참이 되기를 기다립니다. 본문에는 Python의 무동작 문장인 pass 를 사용합니다. 들여쓰기된 모든 블록에는 최소한 하나의 문장이 있어야 하며, pass 가 “여기서는 아무것도 하지 않는다”고 말하는 방법입니다:

    while not ready():
        pass
    proceed()
    
  • 상태 기계(state machine) – 상태 변수에 따라 무엇을 할지 고르는 하나의 while True: 루프입니다. 작업이 이름 붙은 몇 단계로 깔끔하게 나뉠 때 유용합니다:

    state = "header"
    for line in lines:
        if state == "header":
            if line.startswith("---"):
                state = "body"
        elif state == "body":
            print(line)
    
  • 누적(accumulating) – 시퀀스를 순회하면서 결과를 쌓아 올립니다:

    total = 0
    for x in samples:
        total += x
    mean = total / len(samples)
    

    많은 누적 루프는 내장 함수를 사용한 한 줄짜리 등가물을 가집니다. 적용할 수 있는 경우에는 내장 함수를 활용하십시오:

    • sum() – 이터러블의 모든 항목을 더합니다.

    • max() / min() – 가장 큰 항목 또는 가장 작은 항목.

    • any() – 적어도 하나의 항목이 참 같은 값(truthy)이면 True.

    • all() – 모든 항목이 참 같은 값(truthy)일 때만 True.

    • sorted() – 항목들을 순서대로 담은 새 리스트.

    • len() – 항목의 개수(이터러블이 자신의 길이를 아는 경우).

    >>> samples = [3, 1, 4, 1, 5, 9, 2, 6]
    >>> sum(samples)
    31
    >>> sum(samples) / len(samples)        # mean
    3.875
    >>> max(samples)
    9
    >>> min(samples)
    1
    >>> sorted(samples)
    [1, 1, 2, 3, 4, 5, 6, 9]
    >>> any([False, False, True])
    True
    >>> all([True, True, False])
    False
    

    내장 함수 버전이 같은 루프를 직접 작성하는 것보다 더 짧고, 더 명확하며, 보통 더 빠릅니다.