Skip to main content

반복문

학습 목표

  • forwhile 반복문의 차이를 이해하고 적절히 선택할 수 있다
  • range(), enumerate(), zip()을 활용할 수 있다
  • break, continue, else 절로 반복 흐름을 제어할 수 있다

왜 중요한가

반복문은 데이터를 순회하고 처리하는 핵심 구조입니다. ML/DL에서 학습 루프(Training Loop), 데이터 배치 처리, 에포크 반복 등 거의 모든 작업이 반복문 위에서 동작합니다.

for 반복문

Python의 for문은 이터러블(Iterable) 객체의 요소를 하나씩 순회합니다.
# 리스트 순회
fruits = ["사과", "바나나", "체리"]
for fruit in fruits:
    print(fruit)

# 문자열 순회
for char in "Python":
    print(char, end=" ")  # P y t h o n

# 딕셔너리 순회
config = {"lr": 0.001, "epochs": 10}
for key, value in config.items():
    print(f"{key}: {value}")

range()

# range(stop) - 0부터 stop-1까지
for i in range(5):
    print(i, end=" ")  # 0 1 2 3 4

# range(start, stop) - start부터 stop-1까지
for i in range(2, 7):
    print(i, end=" ")  # 2 3 4 5 6

# range(start, stop, step) - step 간격
for i in range(0, 20, 3):
    print(i, end=" ")  # 0 3 6 9 12 15 18

# 역순
for i in range(10, 0, -1):
    print(i, end=" ")  # 10 9 8 7 6 5 4 3 2 1

enumerate()

인덱스와 값을 동시에 얻을 때 사용합니다.
fruits = ["사과", "바나나", "체리"]

# 비추천 - 인덱스로 접근
for i in range(len(fruits)):
    print(f"{i}: {fruits[i]}")

# 추천 - enumerate 사용
for idx, fruit in enumerate(fruits):
    print(f"{idx}: {fruit}")

# 시작 인덱스 지정
for idx, fruit in enumerate(fruits, start=1):
    print(f"{idx}. {fruit}")
# 1. 사과
# 2. 바나나
# 3. 체리

zip()

여러 이터러블을 동시에 순회합니다.
names = ["김철수", "이영희", "박민수"]
scores = [85, 92, 78]
grades = ["B", "A", "C"]

# 두 리스트 동시 순회
for name, score in zip(names, scores):
    print(f"{name}: {score}점")

# 세 리스트 동시 순회
for name, score, grade in zip(names, scores, grades):
    print(f"{name}: {score}점 ({grade})")

# 딕셔너리 생성
score_dict = dict(zip(names, scores))
print(score_dict)  # {"김철수": 85, "이영희": 92, "박민수": 78}
zip()은 가장 짧은 시퀀스에 맞춰 종료됩니다. 길이가 다른 경우 itertools.zip_longest()를 사용하세요.

while 반복문

조건이 참인 동안 반복합니다.
# 기본 while
count = 0
while count < 5:
    print(count, end=" ")
    count += 1
# 0 1 2 3 4

# 사용자 입력 대기
while True:
    user_input = input("명령을 입력하세요 (quit으로 종료): ")
    if user_input == "quit":
        break
    print(f"입력: {user_input}")

# 수렴 조건
epsilon = 1e-6
value = 100.0
while value > epsilon:
    value /= 2
    print(f"{value:.8f}")

흐름 제어

break와 continue

# break - 반복 즉시 종료
for i in range(10):
    if i == 5:
        break
    print(i, end=" ")  # 0 1 2 3 4

# continue - 현재 반복 건너뛰기
for i in range(10):
    if i % 2 == 0:
        continue
    print(i, end=" ")  # 1 3 5 7 9

for-else와 while-else

else 절은 반복이 break 없이 정상 종료되었을 때 실행됩니다.
# 소수 판별
def is_prime(n):
    if n < 2:
        return False
    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0:
            break
    else:
        # break 없이 반복 완료 -> 소수
        return True
    return False

print(is_prime(17))  # True
print(is_prime(15))  # False

# 검색 패턴
target = 42
data = [10, 20, 30, 42, 50]
for item in data:
    if item == target:
        print(f"{target} 발견!")
        break
else:
    print(f"{target}을 찾지 못함")

중첩 반복문

# 구구단
for i in range(2, 10):
    for j in range(1, 10):
        print(f"{i}x{j}={i*j:2d}", end="  ")
    print()

# 2차원 탐색
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
for i, row in enumerate(matrix):
    for j, val in enumerate(row):
        if val == 5:
            print(f"5는 ({i}, {j}) 위치")

AI/ML에서의 활용

# 학습 루프 기본 패턴
num_epochs = 10
for epoch in range(num_epochs):
    # 배치 순회
    for batch_idx, (data, target) in enumerate(train_loader):
        # 순전파
        output = model(data)
        loss = criterion(output, target)

        # 역전파
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

    # 에포크 종료 시 검증
    val_loss = evaluate(model, val_loader)
    print(f"Epoch {epoch+1}/{num_epochs}, Val Loss: {val_loss:.4f}")

# 그리드 서치
best_score = 0
best_params = None
for lr in [0.001, 0.01, 0.1]:
    for batch_size in [16, 32, 64]:
        score = train_and_evaluate(lr=lr, batch_size=batch_size)
        if score > best_score:
            best_score = score
            best_params = {"lr": lr, "batch_size": batch_size}

print(f"최적 파라미터: {best_params}, 점수: {best_score}")
반복 횟수가 정해져 있거나 이터러블을 순회할 때는 for를, 조건에 따라 반복을 계속할지 결정할 때는 while을 사용합니다. 대부분의 경우 for가 더 적합합니다.
빈도는 높지 않지만, 검색/탐색 패턴에서 유용합니다. “찾으면 break, 못 찾으면 else” 패턴이 플래그 변수 없이 깔끔하게 표현됩니다.

체크리스트

  • forwhile의 적절한 사용 상황을 구분할 수 있다
  • range(), enumerate(), zip()을 활용할 수 있다
  • break, continue, else 절로 흐름을 제어할 수 있다
  • 중첩 반복문을 구현할 수 있다

다음 문서