PYTHON

파이썬 for 반복문 — 장바구니 영수증으로 익히는 range와 빠지는 끝 번호

PANCO_IT
#파이썬#python#for문#반복문#range#파이썬기초#파이썬독학#리스트#누적합

슈퍼마켓 진열대에 사과가 줄지어 놓여 있고 가격표가 붙어 있는 모습

이미지 출처: Pexels, Pixabay · Pexels License

7편의 장바구니에 값을 붙여 봅니다. 사과 3,000원, 우유 2,500원, 계란 6,000원, 빵 4,200원, 커피 8,900원. 계산대에서 물건이 하나씩 지나갈 때마다 합계가 올라가는 영수증을 코드로 만드는 것이 오늘 할 일입니다. 완성하면 이렇게 찍힙니다.

사과 3000 누적 3000
우유 2500 누적 5500
계란 6000 누적 11500
빵 4200 누적 15700
커피 8900 누적 24600
합계 24600

print를 여섯 줄 쓰면 지금 당장은 됩니다. 물건이 여섯 개가 되면 한 줄을 더 쓰고, 값이 바뀌면 여섯 줄을 다 고칩니다. 물건이 몇 개든 같은 코드로 끝내려면 "하나씩 꺼내서 같은 일을 반복하는" 문법이 필요합니다. 그것이 for 반복문입니다.

for는 칸을 하나씩 꺼내 주는 문법입니다

파이썬 공식 자습서는 for 문을 이렇게 정의합니다. 리스트나 문자열 같은 시퀀스의 항목들을, 그 시퀀스에 들어 있는 순서대로 하나씩 꺼내 처리하는 문장. 다른 언어의 for가 "몇 번 돌아라"에 가깝다면, 파이썬의 for는 "이 묶음에서 하나씩 꺼내라"에 가깝습니다. 그래서 횟수를 세는 변수 없이 리스트를 통째로 넘기면 됩니다.

쓰는 순간은 같은 일을 값만 바꿔 여러 번 할 때입니다. 장바구니 값 더하기, 점수 열 개 평균 내기, 문장의 글자를 한 자씩 검사하기. 개수가 몇이든 코드는 한 덩어리입니다.

어두운 코드 상자에 for item in cart: 한 줄과 들여쓴 print(item), 들여쓰기 없는 print("끝")이 있고, for·item·cart·콜론 네 조각에 색 밑줄이 그어져 오른쪽 주석 카드 네 장이 각각 반복 시작 낱말, 이번 차례 값이 담기는 이름, 값을 꺼내 올 리스트, 콜론 뒤 들여쓴 블록이라고 설명하며, 아래 상자에 item이 사과·우유·계란으로 바뀌다 칸이 끝나면 블록 밖으로 나간다는 순서가 적힌 그림

for 한 줄은 네 조각입니다. 꺼낼 묶음, 담을 이름, 그리고 콜론 뒤에 들여쓴 블록. 들여쓰기가 없는 줄은 반복이 다 끝난 뒤 한 번만 실행됩니다.

성질은 넷입니다.

성질아래 코드에서
순서대로 꺼낸다리스트에 든 순서 그대로, 앞에서 뒤로사과 → 우유 → 계란 → 빵 → 커피
이름이 매번 바뀐다item에 이번 차례 값이 새로 담긴다첫 바퀴 item은 사과, 둘째 바퀴는 우유
블록만 반복된다콜론 뒤 들여쓴 줄만 매번 돈다. 6편 if의 들여쓰기 규칙 그대로print(item)은 다섯 번, print("끝")은 한 번
묶음은 리스트가 아니어도 된다문자열, range, 나중에 배울 딕셔너리도 돈다for ch in "빵", for n in range(5)

앞으로 이 뜻으로 쓰는 낱말입니다.

용어
반복문(loop)같은 블록을 여러 번 실행시키는 문장. for와 while 둘
반복 변수for item in cartitem. 매 바퀴 새 값이 담기는 이름
시퀀스(sequence)순서가 있는 값의 묶음. 리스트, 문자열, range
한 바퀴블록이 한 번 실행되는 것. 반복 변수 값 하나에 한 바퀴
range(시작, 끝, 간격)정수를 순서대로 만들어 주는 묶음. 끝 번호는 포함되지 않는다

첫 시도 — 1부터 10까지 더했는데 45

영수증 전에 몸풀기로 1부터 10까지의 합을 구합니다. 답은 55. 반복할 값이 정수라면 리스트를 손으로 쓰는 대신 range에 시킵니다.

1부터 10까지의 합 — 첫 시도
total = 0
for n in range(1, 10):
  total = total + n
print(total)

📱 코드 실행(실습)은 태블릿·PC에서 이용할 수 있어요. 모바일에서는 위 코드를 눈으로 따라가며 확인하세요.

45

55가 아니라 45입니다. 10이 빠진 값. range(1, 10)이 만든 수를 눈으로 보면 이유가 드러납니다.

range가 실제로 만드는 수를 리스트로 펼쳐 보기
print(list(range(1, 10)))
print(list(range(5)))
print(list(range(1, 11)))
print(list(range(0, 10, 3)))
print(list(range(10, 0, -2)))

📱 코드 실행(실습)은 태블릿·PC에서 이용할 수 있어요. 모바일에서는 위 코드를 눈으로 따라가며 확인하세요.

[1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[0, 3, 6, 9]
[10, 8, 6, 4, 2]

첫 줄이 9에서 끝납니다. range(1, 10)은 "1부터 10까지"가 아니라 **"1부터 시작해 10 앞에서 멈춘다"**입니다. 7편 슬라이싱의 cart[1:4]가 4번 칸을 빼고 세 칸만 주던 것과 같은 규칙입니다. 공식 문서의 표현을 빌리면 끝값은 만들어지는 수열에 포함되지 않고, range(10)은 길이 10인 리스트의 올바른 인덱스 열 개를 만듭니다. 0부터 9까지. 리스트 번호가 0에서 시작하니 끝을 빼야 개수가 딱 맞습니다.

0부터 12까지 눈금이 있는 수직선 위에 1부터 10까지 열 개의 파란 점이 찍혀 있고 위쪽에 열 개 1부터 10까지라는 괄호 표시가 있으며, 11 자리에는 빨간 점선 원과 11은 끝 번호라 빠집니다라는 메모가 있고, 아래 표에 range(5)는 0 1 2 3 4, range(1, 11)은 1부터 10, range(0, 10, 3)은 0 3 6 9와 각각의 설명이 적힌 그림

range(1, 11)이 만드는 수는 1부터 10까지 열 개입니다. 끝에 적은 11은 들어오지 않습니다. 숫자 하나면 0부터, 셋이면 세 번째가 건너뛰는 간격입니다.

그러니 10까지 더하려면 끝에 11을 적습니다.

끝 번호를 하나 올린 고친 코드
total = 0
for n in range(1, 11):
  total += n
print(total)
print(n)

📱 코드 실행(실습)은 태블릿·PC에서 이용할 수 있어요. 모바일에서는 위 코드를 눈으로 따라가며 확인하세요.

55
10

55입니다. total += ntotal = total + n을 줄여 쓴 것으로 5편 연산자에서 본 표기입니다. 마지막 줄의 print(n)은 반복이 끝난 뒤에 찍은 값인데 10이 나옵니다. 반복 변수는 블록이 끝나도 사라지지 않고 마지막 값을 그대로 갖고 있습니다. 나중에 같은 이름을 다른 뜻으로 쓰면 헷갈리는 자리라 알아 두는 편이 좋습니다.

range가 리스트를 미리 만들어 두는 것은 아닙니다. print(range(10))을 하면 [0, 1, …]이 아니라 range(0, 10)이라고만 나옵니다. 돌 때마다 다음 수를 하나씩 내주는 물건이라 백만까지 돌려도 백만 칸짜리 리스트가 생기지 않습니다. 그래서 위에서 눈으로 보려고 list(range(…))로 한 번 감쌌습니다.

리스트는 range 없이 그대로 돕니다

영수증으로 돌아옵니다. 값이 정수가 아니라 장바구니라면 range가 필요 없습니다. 리스트를 in 뒤에 그대로 놓으면 칸을 하나씩 꺼내 줍니다.

장바구니를 그대로 돌기 — 이름과 글자 수
cart = ["사과", "우유", "계란", "빵", "커피"]
for item in cart:
  print(item, len(item))
print("끝")

📱 코드 실행(실습)은 태블릿·PC에서 이용할 수 있어요. 모바일에서는 위 코드를 눈으로 따라가며 확인하세요.

사과 2
우유 2
계란 2
빵 1
커피 2
끝

item에 사과, 우유, 계란, 빵, 커피가 차례로 담기고 블록이 다섯 번 돕니다. print("끝")은 들여쓰기가 없어 한 번. 가격 리스트도 같은 모양으로 돌면서 더하면 합계가 나옵니다.

가격을 하나씩 더하기 — 합계 24600
prices = [3000, 2500, 6000, 4200, 8900]
total = 0
for p in prices:
  total += p
  print(p, "누적", total)
print("합계", total)

📱 코드 실행(실습)은 태블릿·PC에서 이용할 수 있어요. 모바일에서는 위 코드를 눈으로 따라가며 확인하세요.

3000 누적 3000
2500 누적 5500
6000 누적 11500
4200 누적 15700
8900 누적 24600
합계 24600

total은 반복 에서 0으로 시작해야 합니다. 블록 안에 total = 0을 넣으면 매 바퀴 0으로 되돌아가 마지막 값 8,900만 남습니다. 초보 코드에서 자주 보는 실수라 그림으로 한 번 짚어 둡니다.

다섯 개의 막대가 왼쪽부터 사과 3,000, 우유 5,500, 계란 11,500, 빵 15,700, 커피 24,600으로 점점 높아지고, 각 막대의 위쪽 진한 부분이 이번 바퀴에 더한 값이며 연한 부분이 이전까지의 누적이고, 오른쪽에 total += p 한 바퀴에 한 번이라는 메모 카드가 살짝 기울어 붙은 막대 그림

total은 반복 밖에서 0으로 시작해 한 바퀴마다 한 번씩 자랍니다. 진한 칸이 이번 바퀴에 더한 값입니다. 반복이 끝난 뒤 print(total)이 찍는 것은 마지막 막대의 24,600입니다.

이름과 가격을 나란히 — range(len(…))

영수증에는 물건 이름과 값이 한 줄에 같이 찍혀야 합니다. 리스트가 둘인데 for는 한 번에 하나만 돕니다. 이럴 때 range가 다시 나옵니다. 두 리스트의 칸 번호를 돌면 같은 번호로 양쪽을 꺼낼 수 있습니다.

칸 번호로 두 리스트를 같이 읽기
cart = ["사과", "우유", "계란", "빵", "커피"]
prices = [3000, 2500, 6000, 4200, 8900]
for i in range(len(cart)):
  print(i, cart[i], prices[i])

📱 코드 실행(실습)은 태블릿·PC에서 이용할 수 있어요. 모바일에서는 위 코드를 눈으로 따라가며 확인하세요.

0 사과 3000
1 우유 2500
2 계란 6000
3 빵 4200
4 커피 8900

len(cart)가 5이니 range(5), 곧 0부터 4까지. 칸이 다섯이면 마지막 번호는 4라던 7편 규칙이 여기서 range의 끝 빠짐과 정확히 맞물립니다. 끝을 빼기 때문에 range(len(cart))는 언제나 리스트의 번호와 같은 범위가 됩니다. 이 궁합 덕에 range(len(리스트))는 파이썬 코드에서 관용구처럼 쓰입니다. 공식 문서는 번호와 값이 같이 필요할 때 enumerate가 더 편하다고 덧붙이는데, 그 함수는 다음 시즌에서 다룹니다.

세 번째 시도 — 돌면서 지웠더니 계란이 남았습니다

계산을 마친 물건을 장바구니에서 빼는 코드를 붙여 봅니다. 우유와 계란은 이미 샀다고 치고 지웁니다.

돌면서 지우기 — 결과를 예상하고 실행해 보세요
cart = ["사과", "우유", "계란", "빵", "커피"]
for item in cart:
  if item == "우유" or item == "계란":
      cart.remove(item)
print(cart)

📱 코드 실행(실습)은 태블릿·PC에서 이용할 수 있어요. 모바일에서는 위 코드를 눈으로 따라가며 확인하세요.

['사과', '계란', '빵', '커피']

우유는 지워졌는데 계란이 남았습니다. 에러도 없습니다. for는 리스트를 칸 번호 순서로 읽습니다. 둘째 바퀴에 1번 칸 우유를 지우면 뒤에 있던 계란이 1번 칸으로 당겨 오는데, for는 다음 바퀴에 2번 칸을 봅니다. 그 자리에는 빵이 와 있습니다. 계란은 검사를 받지 못한 채 지나갑니다.

위쪽 선반에 사과·우유·계란·빵·커피 다섯 칸이 있고 우유 칸이 노랗게 칠해져 두 번째 바퀴에 우유를 지운다고 적혀 있으며, 아래 선반은 사과·계란·빵·커피 네 칸으로 줄어 계란이 1번 칸으로 당겨졌지만 빵 칸이 노랗게 칠해져 for는 2번 칸으로 간다고 적혀 있고, 계란 칸에 빨간 점선 테두리와 검사도 못 받고 남는다는 메모가 있으며, 맨 아래 초록 상자에 cart[:] 사본을 돌기와 keep 새 리스트 만들기 두 가지 고치는 법이 적힌 그림

돌고 있는 리스트를 지우면 뒤 칸이 앞으로 당겨지고, for는 다음 번호로 넘어갑니다. 당겨온 값은 검사를 건너뜁니다. 사본을 돌거나 새 리스트를 만들면 됩니다.

공식 문서는 이 상황을 두고 컬렉션을 돌면서 같은 컬렉션을 고치는 코드는 올바르게 만들기 어렵다고 적고, 사본을 돌거나 새 컬렉션을 만들라고 권합니다. 둘 다 7편에서 본 문법입니다.

사본을 돌기 — cart[:]가 복사본이었습니다
cart = ["사과", "우유", "계란", "빵", "커피"]
for item in cart[:]:
  if item == "우유" or item == "계란":
      cart.remove(item)
print(cart)

cart = ["사과", "우유", "계란", "빵", "커피"]
keep = []
for item in cart:
  if item != "우유" and item != "계란":
      keep.append(item)
print(keep)

📱 코드 실행(실습)은 태블릿·PC에서 이용할 수 있어요. 모바일에서는 위 코드를 눈으로 따라가며 확인하세요.

['사과', '빵', '커피']
['사과', '빵', '커피']

첫 방법은 cart[:]로 만든 복사본을 돌면서 원본을 지웁니다. 복사본은 줄어들지 않으니 다섯 바퀴가 온전히 돕니다. 둘째 방법은 남길 것만 새 리스트에 담습니다. 저는 둘째 쪽을 더 자주 씁니다. 지우는 코드보다 남기는 코드가 읽을 때 뜻이 분명해서입니다.

완성 — 영수증 열 줄

세 번의 시도를 합치면 처음에 보여 드린 영수증이 됩니다. 이름과 값을 같이 읽어야 하니 range(len(cart)), 합계는 반복 밖에서 0, 계산이 끝난 뒤 장바구니는 새 리스트로.

완성 코드 — 값을 바꿔 가며 출력을 예상해 보세요
cart = ["사과", "우유", "계란", "빵", "커피"]
prices = [3000, 2500, 6000, 4200, 8900]

total = 0                          # 반복 밖에서 시작
for i in range(len(cart)):         # 0부터 4까지 — 끝 5는 빠집니다
  total += prices[i]             # 한 바퀴에 한 번
  print(cart[i], prices[i], "누적", total)
print("합계", total)

paid = []                          # 새 리스트에 담는 쪽
for item in cart:
  if item != "우유":
      paid.append(item)
print(paid)

📱 코드 실행(실습)은 태블릿·PC에서 이용할 수 있어요. 모바일에서는 위 코드를 눈으로 따라가며 확인하세요.

사과 3000 누적 3000
우유 2500 누적 5500
계란 6000 누적 11500
빵 4200 누적 15700
커피 8900 누적 24600
합계 24600
['사과', '계란', '빵', '커피']

물건이 여섯 개가 되면 두 리스트에 한 칸씩만 붙이면 됩니다. 코드는 한 글자도 안 바뀝니다. 그것이 반복문을 쓰는 이유입니다.

조금 더 — 문자열도 돌고, 거꾸로도 돕니다

in 뒤에 올 수 있는 것은 리스트만이 아닙니다. 문자열을 놓으면 글자가 한 자씩 나옵니다. range의 세 번째 자리에 음수를 주면 거꾸로 셉니다.

문자열 한 자씩, 그리고 거꾸로 세기
for ch in "파이썬":
  print(ch, end=" ")
print()
for n in range(10, 0, -2):
  print(n, end=" ")
print()
print(sum(range(1, 11)))

📱 코드 실행(실습)은 태블릿·PC에서 이용할 수 있어요. 모바일에서는 위 코드를 눈으로 따라가며 확인하세요.

파 이 썬
10 8 6 4 2
55

end=" "는 줄을 바꾸지 않고 한 칸 띄우라는 뜻으로, 2편 print에서 나온 옵션입니다. range(10, 0, -2)는 10에서 시작해 2씩 줄이며 0 앞에서 멈춥니다. 마지막 줄의 sum(range(1, 11))은 for 없이 합을 구한 것입니다. 이렇게 묶음을 통째로 받는 함수가 많아서, range가 리스트를 만들지 않고도 쓸모가 있습니다.

반복을 중간에 끊는 break와 한 바퀴만 건너뛰는 continue, 그리고 조건이 참인 동안 계속 도는 while은 다음 편에서 다룹니다. 무한 루프를 스스로 멈추는 법이 그 편의 주제입니다. 예제는 파이썬 3 기준이며 2026년 9월 8일 작성했습니다.

for 하나로 본 문법 아홉 개

cart = ["사과", "우유", "계란"], prices = [3000, 2500, 6000]일 때입니다.

문법결과
for x in 묶음:묶음에서 하나씩 꺼내 x에 담고 블록 실행for item in cart:세 바퀴
들여쓴 블록매 바퀴 실행되는 줄 print(item)사과, 우유, 계란
range(끝)0부터 끝 앞까지range(3)0, 1, 2
range(시작, 끝)시작부터 끝 앞까지range(1, 4)1, 2, 3
range(시작, 끝, 간격)간격만큼 건너뛰며, 음수면 거꾸로range(6, 0, -2)6, 4, 2
range(len(리스트))리스트의 칸 번호 전부range(len(cart))0, 1, 2
total += x반복 밖에서 0으로 시작해 누적total += prices[i]11500
for ch in 문자열:글자 한 자씩for ch in "빵":
돌면서 원본 수정칸이 당겨져 건너뜀. 사본(cart[:])이나 새 리스트로for item in cart[:]:다섯 바퀴 온전히

끝 번호를 바꾸면 출력은 어떻게 될까요

미니 퀴즈

OX 3문제 + 4지선다 4문제

참고 자료

정의와 동작은 파이썬 공식 문서를 기준으로 확인했습니다. 한국어 번역본입니다.


포켓코딩(PYTHON1) 8편 · 7편(파이썬 리스트)에서 이어집니다. 예제 코드는 강사 개인 GitHub 저장소의 연습 문제를 바탕으로 다시 썼습니다. 다음 편: 파이썬 while과 무한 루프 — 멈출 조건은 내가 만듭니다.

PANCO_IT

IT 지식을 정리하는 개발자

관련 글