결론부터 보기
처리할 iterable의 항목이 있다면 for를, 특정 조건이 참인 동안 반복해야 한다면 while을 먼저 검토한다. Python의 for는 단순한 ‘횟수 반복문’이 아니라 iterable에서 항목을 하나씩 받아 순회하는 문장이다.
도구 | 선택 기준 | 대표 상황 |
|---|---|---|
for | iterable의 각 항목을 처리 | 행, 파일, 키, 정해진 범위 순회 |
while | 종료 조건이 될 때까지 반복 | 재시도, 입력 대기, 상태 변화 |
for·range·enumerate로 데이터 순회하기
range(start, stop, step)는 정수의 불변 산술 시퀀스를 나타내며 stop은 포함하지 않는다. 실제 데이터 항목이 아니라 정수 범위가 필요할 때 사용한다.
for batch_number in range(1, 4):
print(f"batch {batch_number}")
batch 1
batch 2
batch 3
항목과 순번이 함께 필요하면 range(len(items))로 다시 인덱싱하기보다 enumerate(items)를 사용한다. iterable에서 항목을 직접 받으면서 카운터도 얻어 의도가 선명하고 인덱스 실수를 줄인다. start로 첫 번호를 바꿀 수 있다.
scores = [88, 91, 76]
for row_number, score in enumerate(scores, start=1):
print(row_number, score)
1 88
2 91
3 76
while은 종료 조건을 코드로 보이게 만든다
while은 매 반복 전에 조건을 다시 평가한다. 조건에 쓰인 상태를 갱신하지 않으면 무한 반복이 될 수 있으므로 최대 횟수나 시간 제한처럼 안전한 경계를 둔다.
attempt = 0
max_attempts = 3
while attempt < max_attempts:
attempt += 1
print(f"attempt {attempt}")
if attempt == 2:
print("connected")
break
else:
print("failed")
attempt 1
attempt 2
connected
break·continue로 흐름 제어하기
break는 가장 가까운 반복문을 즉시 끝낸다. continue는 현재 항목의 남은 코드를 건너뛰고 다음 반복으로 간다. 무시할 항목을 초반에 continue하는 guard 형태는 깊은 중첩을 줄이는 데 유용하다.
raw_values = ["10", "", "bad", "20"]
valid = []
for item in raw_values:
if not item:
continue
if not item.isdigit():
print(f"stopped: {item}")
break
valid.append(int(item))
print(valid)
stopped: bad
[10]
반복문의 else는 break가 없을 때 실행된다
for의 iterable이 정상 소진되거나 while 조건이 거짓이 되어 끝나면 else가 실행된다. 반복이 한 번도 실행되지 않았을 때만 실행되는 문법이 아니다. break로 빠져나가면 건너뛰고, continue만으로는 건너뛰지 않는다. 반복 중 처리되지 않은 예외가 전파되면 정상 종료가 아니므로 else까지 도달하지 않는다.
values = [2, 4, 7, 9]
target = 5
for index, value in enumerate(values):
if value == target:
print(f"found at {index}")
break
else:
print("not found")
not found
검색 성공 시 break하고, 끝까지 찾지 못했을 때 else에서 처리하는 구조다. 상태 변수 found = False를 따로 관리하지 않아도 된다.
zip으로 여러 iterable을 나란히 순회하기
zip은 각 iterable에서 같은 순서의 항목을 튜플로 묶는 지연 iterator를 반환한다. 값을 미리 모두 만들지 않으며 순회할 때 소비된다.
names = ["Ada", "Linus"]
scores = [95, 88]
pairs = zip(names, scores)
print(list(pairs))
print(list(pairs))
[('Ada', 95), ('Linus', 88)]
[]
두 번째 결과가 빈 이유는 같은 iterator를 이미 소비했기 때문이다. 다시 필요하면 원본 iterable로 zip을 다시 만들거나, 데이터가 작고 재사용이 꼭 필요할 때만 list로 보관한다. dict(zip(keys, values))처럼 튜플을 딕셔너리 항목으로 변환할 수도 있다.
길이가 다르면 목적에 맞는 정책을 고른다
기본 zip은 가장 짧은 iterable이 끝나면 조용히 멈추고 긴 쪽의 나머지를 버린다. 의도적인 잘라내기라면 사용할 수 있지만, 길이가 같아야 하는 데이터에서는 오류를 숨길 수 있다. Python 3.10 이상에서는 strict=True로 불일치를 ValueError로 바꾼다.
print(list(zip([1, 2], ["a"])))
try:
list(zip([1, 2], ["a"], strict=True))
except ValueError as error:
print(type(error).__name__)
[(1, 'a')]
ValueError
zip_longest는 누락을 보존해야 할 때 사용한다
itertools.zip_longest는 가장 긴 iterable이 끝날 때까지 순회하고 짧은 쪽의 누락을 fillvalue로 채운다. 데이터 손실 없이 불일치 자체를 후속 검증해야 할 때 사용한다.
from itertools import zip_longest
rows = zip_longest([1, 2], ["a"], fillvalue="MISSING")
print(list(rows))
[(1, 'a'), (2, 'MISSING')]
입력 중 하나가 무한할 수 있다면 zip_longest도 끝나지 않을 수 있다. islice나 takewhile 같은 명시적 제한을 함께 둔다.
순회 중 같은 컬렉션을 수정하지 않는다
리스트를 순회하면서 그 리스트의 항목을 제거하거나 삽입하면 다음 항목을 건너뛰거나 같은 항목을 다시 처리할 수 있다. 수정이 필요하면 복사본을 순회하거나 새 컬렉션을 만든다.
numbers = [1, -2, 3, -4]
for number in numbers.copy():
if number < 0:
numbers.remove(number)
print(numbers)
[1, 3]
필터링 결과를 새 리스트로 만드는 컴프리헨션은 9번 글에서, 데이터를 하나씩 지연 생성하는 generator는 11번 글에서 자세히 다룬다.
실전: 두 컬럼을 검증하며 결합하기
names = ["Ada", "Linus"]
scores = [88, None]
for row_number, (name, score) in enumerate(
zip(names, scores, strict=True), start=1
):
if score is None:
print(row_number, name, "missing")
continue
print(row_number, name, score)
1 Ada 88
2 Linus missing
strict zip으로 두 컬럼의 행 수 계약을 검증하고, enumerate로 사람이 읽는 행 번호를 붙이며, guard continue로 누락 처리 뒤의 정상 경로를 단순하게 유지했다.
흔한 실수와 핵심 체크리스트
☐ iterable 항목 순회는 for, 조건 기반 반복은 while을 먼저 검토한다.
☐ 순번과 항목이 함께 필요하면 enumerate와 start를 사용한다.
☐ while의 상태 갱신과 최대 반복 또는 종료 경계를 코드에서 확인한다.
☐ loop else는 break 없이 정상 종료했을 때 실행된다고 설명할 수 있다.
☐ zip이 한 번 소비되는 lazy iterator이며 기본적으로 짧은 입력에서 멈춤을 안다.
☐ 같은 길이가 계약이면 strict=True, 누락 보존이면 zip_longest를 선택한다.
☐ 순회 중 원본 컬렉션을 수정하지 않고 복사본 순회나 새 결과 생성을 사용한다.
다음 글: 리스트·튜플·집합·딕셔너리 비교
반복문은 어떤 iterable도 순회할 수 있지만 자료구조마다 순서, 중복, 변경 가능성, 조회 방식이 다르다. 다음 글에서는 리스트·튜플·집합·딕셔너리를 같은 기준으로 비교해 데이터에 맞는 구조를 고른다.
참고 자료
Python 튜토리얼의 for 문 — iterable 순회와 순회 중 컬렉션 수정 주의 (2026-08-03 확인)
Python while·for 언어 레퍼런스 — 반복 조건, break·continue와 loop else의 실행 조건 (2026-08-03 확인)
Python enumerate·range 공식 문서 — 카운터와 항목 반환, start 및 정수 범위의 의미 (2026-08-03 확인)
Python zip 공식 문서 — lazy iterator, 최단 입력 종료와 strict=True 길이 검증 (2026-08-03 확인)
Python itertools.zip_longest 공식 문서 — 가장 긴 입력까지 순회하고 fillvalue로 누락을 채우는 규칙 (2026-08-03 확인)
댓글 0
댓글을 불러오는 중…