모든 강의를 무료로 볼 수 있어요. 회원가입 없이도 학습 가능합니다.

15강 / 전체 32강

루프 제어 — break, continue, pass, for-else

10분 읽기 조회 4

break·continue·pass의 정확한 동작과 파이썬 고유의 for-else 패턴을 마스터한다.

🎯 이 강의에서 배우는 것

파이썬의 루프 제어 키워드인 break, continue, pass와 파이썬 고유의 for-else / while-else 패턴을 완전히 이해합니다. 특히 for-else는 다른 언어에는 없는 파이썬만의 구문으로, 탐색 루프를 우아하게 표현하는 강력한 도구입니다.

🛑 break — 루프 즉시 탈출

# break는 자신이 속한 루프 하나만 종료
nums = [3, 7, -2, 5, 9, -1]

# 첫 번째 음수 위치 찾기
for i, n in enumerate(nums):
    if n < 0:
        print(f"첫 음수: 인덱스 {i}, 값 {n}")
        break   # 찾았으니 더 볼 필요 없음
# "첫 음수: 인덱스 2, 값 -2"

# break 없이 짰을 때의 문제
found_idx = -1
for i, n in enumerate(nums):
    if n < 0:
        found_idx = i
        break   # 없으면 마지막 음수를 저장 (잘못된 결과)

# 중첩 루프에서 break: 자신이 속한 루프만 종료
for i in range(3):
    for j in range(3):
        if j == 1:
            break   # 안쪽 루프만 종료
        print(f"({i},{j})", end=" ")
    print()
# (0,0)
# (1,0)
# (2,0)

🔀 중첩 루프 전체 탈출 전략

matrix = [[1, 0, 3], [4, 5, 0], [7, 8, 9]]

# 방법 1: flag 변수 (단점: 루프마다 flag 체크 필요)
found = False
for i in range(len(matrix)):
    for j in range(len(matrix[i])):
        if matrix[i][j] == 0:
            found = True
            break
    if found:
        break
print(f"flag 방법: ({i},{j})")

# 방법 2: 함수로 감싸서 return (권장 — 가장 명확)
def find_zero(matrix):
    for i, row in enumerate(matrix):
        for j, val in enumerate(row):
            if val == 0:
                return (i, j)   # 즉시 함수 종료
    return None   # 없으면 None

result = find_zero(matrix)
print(f"함수 방법: {result}")   # (0, 1)

# 방법 3: 예외 던지기 (극단적 상황에만)
class FoundException(Exception):
    def __init__(self, row, col):
        self.row, self.col = row, col

try:
    for i, row in enumerate(matrix):
        for j, val in enumerate(row):
            if val == 0:
                raise FoundException(i, j)
except FoundException as e:
    print(f"예외 방법: ({e.row},{e.col})")

⏭️ continue — 이번 반복 건너뛰기

# continue는 현재 iteration의 나머지를 건너뛰고 다음 iteration으로
for i in range(10):
    if i % 2 == 0:
        continue   # 짝수 건너뜀
    print(i, end=" ")  # 1 3 5 7 9
print()

# 필터링 패턴: continue로 중첩 줄이기
# 나쁜 예 (깊은 중첩)
data = [{"name": "홍길동", "age": 25, "active": True},
        {"name": "이순신", "age": 17, "active": True},
        {"name": "강감찬", "age": 30, "active": False}]

results_bad = []
for user in data:
    if user["active"]:
        if user["age"] >= 18:
            results_bad.append(user["name"])

# 좋은 예: continue로 평탄하게
results_good = []
for user in data:
    if not user["active"]:
        continue   # 비활성 건너뜀
    if user["age"] < 18:
        continue   # 미성년자 건너뜀
    results_good.append(user["name"])

print(results_good)  # ['홍길동']

# while 루프에서 continue
n = 0
while n < 20:
    n += 1
    if n % 3 == 0 or n % 5 == 0:
        continue   # 3의 배수나 5의 배수 건너뜀
    print(n, end=" ")  # 3, 5, 6... 이 아닌 나머지
print()

🐍 for-else / while-else — 파이썬 고유의 패턴

else 블록은 break 없이 루프가 정상 종료됐을 때만 실행됩니다. "끝까지 탐색했는데 못 찾았을 때" 처리에 최적입니다:

# 소수 판별 — for-else의 교과서적 활용
def is_prime(n):
    if n < 2:
        return False
    for divisor in range(2, int(n**0.5) + 1):
        if n % divisor == 0:
            # 나눠지면 소수가 아님 → break로 루프 탈출
            break
    else:
        # break 없이 루프 완료 → 소수!
        return True
    return False

for num in [2, 3, 4, 17, 20, 97]:
    print(f"{num}: {'소수' if is_prime(num) else '합성수'}")
# 2: 소수, 3: 소수, 4: 합성수, 17: 소수, 20: 합성수, 97: 소수

# 탐색 패턴 비교
# for-else 없이 (flag 변수 필요)
def find_user_flag(users, name):
    found = False
    for user in users:
        if user["name"] == name:
            found = True
            print(f"찾음: {user}")
            break
    if not found:
        print(f"{name}를 찾지 못함")

# for-else 사용 (더 파이썬답고 명확)
def find_user(users, name):
    for user in users:
        if user["name"] == name:
            print(f"찾음: {user}")
            break
    else:
        print(f"{name}를 찾지 못함")

users = [{"name": "홍길동", "score": 85}]
find_user(users, "홍길동")    # 찾음: {'name': '홍길동', 'score': 85}
find_user(users, "없는사람")  # 없는사람를 찾지 못함

# while-else: 재시도 로직
import random
random.seed(42)

attempt = 0
while attempt < 3:
    attempt += 1
    value = random.randint(1, 5)
    print(f"시도 {attempt}: {value}")
    if value == 3:
        print("성공!")
        break
else:
    print("3번 시도 모두 실패")

🔇 pass와 Ellipsis(...)

# pass: 문법적으로 블록이 필요하지만 아무것도 안 할 때
class EmptyClass:
    pass   # 빈 클래스 (나중에 내용 추가 예정)

def todo_function():
    pass   # 나중에 구현할 함수

# 조건문에서 특정 경우를 무시할 때
for i in range(10):
    if i % 2 == 0:
        pass   # 짝수는 일단 무시 (나중에 처리 추가 예정)
    else:
        print(i, end=" ")
print()

# Ellipsis (...): pass와 비슷하지만 의미가 다름
# 타입 힌트에서 미완성 stub 표시
def not_implemented() -> int:
    ...   # "아직 구현 안 했음"을 명시적으로 표현

# 타입 힌트에서 Callable 표시
from typing import Callable
def apply(func: Callable[..., int], x: int) -> int:
    return func(x)

# numpy 슬라이싱
# import numpy as np
# arr[..., 0]   ← "나머지 모든 차원"의 뜻

# 결론: 구문적으로 블록 채우기 → pass / 미완성 타입/stub → ...

🔁 실전 패턴 — try-except-continue

# 데이터 처리에서 오류 있는 항목만 건너뛰기
raw_data = ["10", "20", "abc", "30", "xyz", "50"]

valid_nums = []
for item in raw_data:
    try:
        valid_nums.append(int(item))
    except ValueError:
        print(f"건너뜀: {item!r}")
        continue   # 오류 항목 건너뛰고 다음으로

print(valid_nums)   # [10, 20, 30, 50]

# 파일 읽기에서 빈 줄 건너뛰기 패턴
lines = ["# 제목", "", "  ", "내용 1", "", "내용 2"]

for line in lines:
    stripped = line.strip()
    if not stripped:           # 빈 줄 건너뜀
        continue
    if stripped.startswith("#"):   # 주석 건너뜀
        continue
    print(f"처리: {stripped}")
# "처리: 내용 1"
# "처리: 내용 2"

⚠️ 자주 하는 실수

  • break와 continue 혼동: break는 루프를 완전히 종료, continue는 현재 반복만 건너뛰고 루프 계속. 대부분의 "건너뛰기"에는 continue를, "탐색 완료"에는 break를 사용하세요.
  • for-else를 if-else처럼 이해: else는 if에 대응하는 것이 아니라 break 없이 루프가 끝났을 때만 실행됩니다. return이나 예외로 루프를 나가도 else는 실행됩니다.
  • 중첩 루프에서 break 범위 오해: break는 자신이 직접 속한 루프만 종료합니다. 전체 탈출이 필요하면 함수로 감싸고 return을 사용하세요.

📝 정리 및 다음 강의 예고

  • break: 자신이 속한 루프 즉시 종료. 중첩 루프 전체 탈출은 함수+return을 사용하세요.
  • continue: 현재 반복 건너뜀. 필터링 로직에서 중첩을 줄이는 데 효과적입니다.
  • for-else: break 없이 루프 완료 시 else 실행. 탐색 실패 처리에 최적입니다.
  • pass: 문법 요건을 채우는 빈 블록. ...는 미완성 stub을 명시적으로 표현합니다.

다음 강의: 리스트 컴프리헨션, 딕셔너리·셋 컴프리헨션, 제너레이터 표현식 — 파이썬다운 표현의 정수를 배웁니다.

관련 주제

  • break·continue 차이
  • for-else 패턴
  • while-else 패턴
  • pass와 Ellipsis
  • 중첩루프 탈출
  • 소수 판별 예제
  • 개발·프로그래밍
  • 개발·프로그래밍 강의
  • 파이썬 기초 40강 — 처음 배우는 프로그래밍
  • 무료강의
  • 무료 온라인 강의
  • NUGUNA
  • 누구나

📚 시리즈 전체 공유

파이썬 기초 40강 — 처음 배우는 프로그래밍

이 강의가 속한 시리즈는 총 32강, 모두 무료입니다. 처음부터 배우려는 동료에게 시리즈 전체를 알려 주세요.

댓글

0/1000

불러오는 중...