9단원 '오류와 예외'의 세 레슨에서 일곱 문제를 내고, 앞 단원(반복과 패턴 · 딕셔너리 · 함수)에서 다섯 문제를 섞었습니다. 눈으로 코드를 따라가 무엇이 찍히는지 쓰거나, 빈칸을 채우고, 잘못된 줄을 고치거나, 짧은 프로그램을 직접 만듭니다.
한 번에 다 풀 필요는 없습니다. 문제 1~10은 폰으로도 풀 수 있고(약 12분), 끝의 만들어 보기 둘은 컴퓨터에서 직접 돌려 봅니다. 이 단원을 건너뛰어도 되는지 보려면 문제 4·7·10을 먼저 풀어 보세요(약 4분). 건너뛸지 볼 때는 힌트를 펴지 않고 풉니다. 세 문제가 모두 맞으면 10단원 첫 레슨 글과 리스트 사이: split·join으로 넘어가고, 하나라도 틀리면 정답 끝에 적힌 '다시 볼 레슨'으로 돌아갑니다.
끝의 두 문제는 프로그램을 직접 만들어 봅니다. 아래 코드 칸에서 바로 고쳐 돌려 볼 수 있고, 내 컴퓨터에서 돌려 보는 길은 내 컴퓨터에서 돌려 보기에 있습니다. 실행 결과는 모두 파이썬 3.15로 돌린 것입니다.
문제 1
문자열 '15'를 정수로 바꾸어 5를 더하는 코드입니다. 무엇이 찍힐까요? 두 줄을 쓰세요.
text = '15'
try:
n = int(text)
print(n + 5)
except ValueError:
print('숫자 아님')
print('끝')
힌트
int('15')는 오류 없이 정수 15를 돌려줍니다. try 안에서 오류가 나지 않았을 때 except 블록과 바깥의 마지막 줄이 어떻게 되는지 보세요.
정답
20
끝- 3~4번 줄:
int('15')가 정수15가 되어15 + 5인20을 찍습니다. - 5~6번 줄:
try안에서 오류가 나지 않았으므로except ValueError:블록은 통째로 건너뜁니다. - 7번 줄: 바깥의
print('끝')이 이어서 실행됩니다.
흔한 오답은 20 다음에 숫자 아님도 함께 적는 것입니다. except 블록도 위에서 아래로 늘 실행된다고 본 것입니다. except 블록은 try 안에서 해당 오류가 났을 때만 실행됩니다.
다시 볼 레슨: try와 except
문제 2
숫자가 아닌 '다섯'을 정수로 바꾸려 합니다. 무엇이 찍힐까요? 두 줄을 쓰세요.
text = '다섯'
try:
print('변환 시작')
n = int(text)
print('성공:', n)
except ValueError:
print('숫자로 적어 주세요')
힌트
3번 줄과 5번 줄 가운데 어느 줄이 오류가 나는 4번 줄보다 앞에 있는지, 4번 줄에서 오류가 난 순간 어디로 이동하는지 보세요.
정답
변환 시작
숫자로 적어 주세요- 3번 줄: 아직 오류가 나기 전이므로
'변환 시작'이 먼저 찍힙니다(규칙 1). - 4번 줄:
int('다섯')에서ValueError가 나는 순간,try안의 남은 5번 줄print('성공:', n)은 건너뛰고 바로 6번 줄except ValueError:로 넘어갑니다. - 7번 줄:
'숫자로 적어 주세요'를 찍고 끝납니다.
흔한 오답은 '변환 시작' 없이 '숫자로 적어 주세요' 한 줄만 쓰는 것입니다. try 안에서 나중에 오류가 나면 앞줄도 취소된다고 본 것입니다. 이미 실행된 3번 줄의 출력은 사라지지 않습니다.
다시 볼 레슨: try와 except
문제 3
세 물건 값 [1500, 2000, 2500]의 합 6000을 구하려 한 코드인데 2500이 나왔습니다. 바퀴마다 찍은 점검 줄을 보고 몇 번째 바퀴에서 예측(1500, 3500, 6000)과 실제가 처음 갈리는지 찾고, 잘못된 줄을 고쳐 쓰세요.
prices = [1500, 2000, 2500]
total = 0
for p in prices:
total = p
print('점검:', p, total)
print(total)
점검: 1500 1500
점검: 2000 2000
점검: 2500 2500
2500힌트
첫 바퀴에서는 0 + 1500과 덮어쓴 1500이 우연히 같습니다. 두 번째 바퀴(p = 2000)에서 기대한 합 3500과 실제 찍힌 값을 견주어 보세요.
정답
두 번째 바퀴(p = 2000)에서 예측(3500)과 실제(2000)가 처음 갈립니다. 4번 줄 total = p를 total = total + p로 고치고 점검용 5번 줄을 지웁니다.
prices = [1500, 2000, 2500]
total = 0
for p in prices:
total = total + p
print(total)60004번 줄 total = p는 앞 바퀴까지 모은 total에 p를 더하지 않고 새 p에 이름을 다시 붙이기만 했습니다(규칙 3).
다시 볼 레슨: 값을 찍어 보며 고치기 · 합 모으기와 세기
문제 4
다음 코드를 실행하면 어떻게 될까요? 알맞은 것을 고르세요.
d = 0
try:
print('나누기 시작')
q = 100 // d
print('몫:', q)
except ValueError:
print('잘못된 값입니다')
- ①
'나누기 시작'이 찍힌 뒤 4번 줄에서ZeroDivisionError로 멈춘다 - ②
'나누기 시작'과'잘못된 값입니다'가 차례로 찍히고 끝난다 - ③ 아무것도 찍지 않고 바로
ZeroDivisionError로 멈춘다 - ④
'나누기 시작','몫: 0','잘못된 값입니다'가 차례로 찍힌다
힌트
4번 줄 100 // 0에서 나는 오류 이름과 6번 줄 except 뒤에 적힌 오류 이름이 같은지 비교해 보세요.
정답
① — 실행 결과는 이렇습니다.
나누기 시작Traceback (most recent call last): File "main.py", line 4, in <module> q = 100 // d ~~~~^^~~ZeroDivisionError: division by zero- ① (정답): 3번 줄에서
'나누기 시작'을 찍은 뒤 4번 줄100 // 0에서ZeroDivisionError가 납니다. 6번 줄은ValueError만 잡으므로 이 오류는 잡히지 않고 멈춥니다. - ②
try로 감싸면 모든 오류를 다 잡아 준다고 봤습니다.except 오류이름:은 지정한 이름과 일치하는 오류만 잡습니다. - ③ 실행하기 전에
ZeroDivisionError를 미리 알아챈다고 봤습니다. 실행 중 오류는 그 줄에 닿을 때 나므로 앞선 3번 줄은 실행됩니다(규칙 1). - ④ 오류가 나도
try안의 남은 줄이 마저 돈다고 봤습니다. 오류가 나는 순간 5번 줄은 건너뜁니다.
다시 볼 레슨: try와 except · 오류 메시지 읽기
문제 5
과일 재고 딕셔너리에서 숫자로 적힌 재고만 골라 합을 구합니다. 무엇이 찍힐까요? 두 줄을 쓰세요.
stock = {
'사과': '10',
'배': '품절',
'감': '5',
}
total = 0
for k in stock:
try:
total += int(stock[k])
except ValueError:
print('제외:', k)
print('재고 합:', total)
힌트
for k in stock:은 키 '사과', '배', '감'을 차례로 꺼냅니다. stock['배']가 '품절'일 때 9번 줄 int('품절')에서 무슨 일이 일어나는지 보세요.
정답
제외: 배
재고 합: 15- 첫 바퀴(
k = '사과'):int('10')이10이 되어total이10이 됩니다. - 두 번째 바퀴(
k = '배'):int('품절')에서ValueError가 나 덧셈이 일어나지 않고except ValueError:로 가서'제외: 배'를 찍습니다. - 세 번째 바퀴(
k = '감'):int('5')가5가 되어total이15가 됩니다.
흔한 오답은 '제외: 품절'로 쓰는 것입니다. k에는 값이 아니라 키 '배'가 들어 있습니다.
다시 볼 레슨: try와 except · 딕셔너리 돌기
문제 6
다음 코드를 실행하면 어떻게 될까요? 알맞은 것을 고르세요.
text = '열'
try:
n = int(text)
except ValueError:
print(n)
- ①
열이 찍히고 끝난다 - ②
0이 찍히고 끝난다 - ③ 5번 줄에서
NameError로 멈춘다
힌트
3번 줄 n = int(text)는 오른쪽 int(text)를 먼저 계산한 뒤 그 결과에 이름 n을 붙입니다(규칙 3). 오른쪽을 계산하다가 오류가 나면 이름 n이 생겼을지 생각해 보세요.
정답
③ — 실행 결과는 이렇습니다.
Traceback (most recent call last): File "main.py", line 3, in <module> n = int(text)ValueError: invalid literal for int() with base 10: '열' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "main.py", line 5, in <module> print(n) ^NameError: name 'n' is not defined3번 줄 오른쪽 int('열')에서 ValueError가 나는 순간 대입이 취소되어 이름 n은 만들어지지 않습니다(규칙 3). 그래서 5번 줄이 없는 이름 n을 읽으려다 NameError로 멈춥니다.
- ① 변환 전의
'열'이n에 들어간다고 봤습니다.'열'이 붙어 있는 이름은text입니다. - ② 오류가 나면
n에 기본값0이 저절로 들어간다고 봤습니다. 파이썬은 기본값을 알아서 넣지 않습니다.
다시 볼 레슨: try와 except · 변수: 값에 이름 붙이기
문제 7
1부터 3 사이의 번호를 받을 때까지 다시 묻는 코드입니다. '가', '0', '2'를 차례로 넣으면 무엇이 찍힐까요? 여섯 줄을 쓰세요.
while True:
raw = input('번호: ')
try:
n = int(raw)
except ValueError:
print('숫자 아님')
continue
if 1 <= n <= 3:
break
print('범위 밖')
print('선택:', n)넣는 값가02
힌트
input('번호: ') 줄은 프롬프트와 입력한 값을 한 줄(번호: 가)로 찍습니다. 세 입력이 각각 첫째 관문(try / except)과 둘째 관문(if 1 <= n <= 3:) 가운데 어디에서 걸리는지 따라가 보세요.
정답
번호: 가
숫자 아님
번호: 0
범위 밖
번호: 2
선택: 2- 첫 바퀴(
'가'):int('가')에서ValueError가 나'숫자 아님'을 찍고continue로 돌아갑니다. - 두 번째 바퀴(
'0'):int('0')은 통과하지만1 <= 0 <= 3이False라break를 건너뛰고'범위 밖'을 찍습니다. - 세 번째 바퀴(
'2'): 두 관문을 모두 통과해break로 나가'선택: 2'를 찍습니다.
흔한 오답은 첫 바퀴에 '숫자 아님' 다음에 '범위 밖'도 함께 적는 것입니다. except 안의 continue가 8~10번 줄을 건너뛰게 한다는 점을 놓친 것입니다.
다시 볼 레슨: 맞는 값이 올 때까지 다시 묻기 · break와 continue
문제 8
점수 [70, 85, 90]에서 80점 이상인 과목 수(2)를 세려는데 1이 찍혔습니다. 점검 출력을 보고 몇 번째 바퀴에서 예측(0, 1, 2)과 실제가 처음 갈리는지 찾고, 어떻게 고쳐야 할지 쓰세요.
scores = [70, 85, 90]
for s in scores:
count = 0
if s >= 80:
count = count + 1
print('점검:', s, count)
print(count)
점검: 70 0
점검: 85 1
점검: 90 1
1힌트
두 번째 바퀴(s = 85)가 끝날 때 count는 1이었습니다. 세 번째 바퀴(s = 90)에 들어가자마자 3번 줄이 count를 무엇으로 바꾸는지 보세요.
정답
세 번째 바퀴(s = 90)에서 예측(2)과 실제(1)가 처음 갈립니다. 3번 줄 count = 0을 for 반복문 위로 옮기고 점검용 6번 줄을 지웁니다.
scores = [70, 85, 90]
count = 0
for s in scores:
if s >= 80:
count = count + 1
print(count)2count = 0이 반복문 안에 있으면 바퀴마다 count를 다시 0에 붙여 앞 바퀴까지 세어 둔 개수가 사라집니다.
다시 볼 레슨: 값을 찍어 보며 고치기 · 세기: 메뉴별로 모으기
문제 9
1부터 5 사이의 숫자를 받을 때까지 다시 묻는 코드입니다. 빈칸 (가)와 (나)에 들어갈 키워드를 차례로 쓰세요.
while True:
raw = input('1~5: ')
try:
n = int(raw)
except ValueError:
print('숫자만 됩니다')
____(가)____
if 1 <= n <= 5:
____(나)____
print('1~5만 됩니다')
힌트
(가)는 변환이 실패했을 때 아래 범위 검사를 건너뛰고 다음 바퀴로 돌아가는 키워드이고, (나)는 범위까지 맞았을 때 반복을 끝내는 키워드입니다.
정답
(가):continue(나):break
while True:
raw = input('1~5: ')
try:
n = int(raw)
except ValueError:
print('숫자만 됩니다')
continue
if 1 <= n <= 5:
break
print('1~5만 됩니다')
print('통과:', n)넣는 값열941~5: 열
숫자만 됩니다
1~5: 9
1~5만 됩니다
1~5: 4
통과: 4흔한 오답은 (가)와 (나)를 거꾸로 쓰는 것입니다. except 안에 break를 쓰면 잘못된 글자를 넣었을 때 다시 묻지 않고 반복이 끝나 버립니다.
다시 볼 레슨: 맞는 값이 올 때까지 다시 묻기 · break와 continue
문제 10
문자열로 적힌 가격에 배달비 3,000원을 더해 돌려주는 함수입니다. '5000'을 넘겼으니 8000이 찍혀야 하는데 '숫자 아님'이 찍혔습니다. 잘못된 두 곳(4번 줄과 5번 줄)을 어떻게 고쳐야 할까요?
def total_pay(raw):
try:
price = int(raw)
return pric + 3000
except:
return '숫자 아님'
print(total_pay('5000'))
숫자 아님힌트
int('5000')은 성공했습니다. 그런데 4번 줄에서 더해 주는 변수 이름 철자를 자세히 보고, 왜 파이썬이 NameError를 내지 않고 6번 줄로 갔는지 5번 줄을 살펴보세요.
정답
4번 줄의 오타 pric을 price로 고치고, 5번 줄의 맨몸 except:를 except ValueError:로 고칩니다.
def total_pay(raw):
try:
price = int(raw)
return price + 3000
except ValueError:
return '숫자 아님'
print(total_pay('5000'))8000고치기 전에는 4번 줄에서 price 대신 pric이라고 잘못 적어 NameError가 났는데, 5번 줄이 오류 이름 없는 except:라 NameError까지 삼켜 버리고 '숫자 아님'을 돌려주었습니다. except ValueError:처럼 잡을 오류 이름을 밝혀 적어야 내 코드의 오타가 숨지 않습니다.
다시 볼 레슨: try와 except · 돌려받은 값 쓰기
문제 11 (만들어 보기)
문자열 리스트 items를 받아, 정수로 바꿀 수 있는 항목만 모두 더해 돌려주는 함수 add(items)를 만들어 봅니다. 정수로 바꿀 수 없는 문자열은 건너뜁니다. 뼈대의 마지막 줄이 이렇게 찍어야 합니다.
13
끝에 print(add(['2', 'y', '4'])) 한 줄을 더해 한 번 더 부르면 이렇게 나와야 합니다.
13
6
아래 뼈대에서 마지막 줄은 그대로 두고, 주석 셋 아래를 채우세요.
def add(items):
# 1. 합을 0으로
# 2. 정수로 바꿔 더하기
# 3. 합 돌려주기
print(add(['5', 'x', '8']))
처음 펼 때 약 6MB를 받습니다.
파이썬 3.14. Tab을 누르면 다음 단추나 칸으로 갑니다. 들여쓰기는 빈칸 네 개입니다. Enter는 앞줄 들여쓰기를 잇고, 콜론 뒤에서는 한 단계 더 들여 씁니다. Ctrl+Enter로 실행합니다.
견줄 시험 값
'실행'을 누르면 여기에 나옵니다.
여기서 쓴 코드 · 내 예상은 저장하지도 운영자에게 보내지도 않습니다. 페이지를 새로 열면 처음 코드입니다.
힌트
for s in items: 안에서 try:로 total += int(s)를 실행하고, except ValueError:에서는 continue를 씁니다.
정답
모범 답입니다.
def add(items):
# 1. 합을 0으로
total = 0
# 2. 정수로 바꿔 더하기
for s in items:
try:
total += int(s)
except ValueError:
continue
# 3. 합 돌려주기
return total
print(add(['5', 'x', '8']))13- 다르게 써도 되는 곳:
n = int(s)와total = total + n을 두 줄로 나누어 써도 같습니다. - 흔한 오답:
try / except를for반복문 바깥에 한 번만 감싸면'x'에서 오류가 나는 순간 반복문 전체가 끝나 버려 뒤의'8'을 더하지 못합니다(5만 돌려줌).return total을for반복문 안에 들여 쓰면 첫 바퀴에서 함수가 끝나 버립니다.
다시 볼 레슨: try와 except · 합 모으기와 세기 · 돌려받은 값 쓰기
문제 12 (만들어 보기)
이번에는 빈 데서 씁니다. 주문 수량(count)으로 1 이상 10 이하의 정수가 들어올 때까지 다시 묻는 프로그램을 만들어 봅니다.
- 프롬프트는
'수량: '으로 합니다. - 정수로 바꿀 수 없는 글자가 들어오면
'숫자만 됩니다'를 찍고 다시 묻습니다. - 정수로 바꿨지만
1 <= count <= 10이 아니면'1~10만 됩니다'를 찍고 다시 묻습니다. - 두 관문을 모두 통과하면 반복을 끝내고 마지막에
'주문:', count를 찍습니다.
'세개', '0', '3'을 차례로 넣으면 이렇게 나와야 합니다.
수량: 세개
숫자만 됩니다
수량: 0
1~10만 됩니다
수량: 3
주문: 3
입력만 '열', '15', '10'으로 바꾸면 이렇게 나와야 합니다.
수량: 열
숫자만 됩니다
수량: 15
1~10만 됩니다
수량: 10
주문: 10
# 1. 계속 묻기
# 2. 바꿀 수 있는지 보기
# 3. 범위 맞으면 나가기넣는 값세개03
처음 펼 때 약 6MB를 받습니다.
파이썬 3.14. Tab을 누르면 다음 단추나 칸으로 갑니다. 들여쓰기는 빈칸 네 개입니다. Enter는 앞줄 들여쓰기를 잇고, 콜론 뒤에서는 한 단계 더 들여 씁니다. Ctrl+Enter로 실행합니다.
견줄 시험 값
input()마다 위에서부터 한 줄씩 들어갑니다.
'실행'을 누르면 여기에 나옵니다.
여기서 쓴 코드 · 넣은 값 · 내 예상은 저장하지도 운영자에게 보내지도 않습니다. 페이지를 새로 열면 처음 코드입니다.
힌트
맞는 값이 올 때까지 다시 묻기의 세 하위 목표(while True: → try / except ValueError:와 continue → if 1 <= count <= 10: break)를 차례대로 씁니다.
정답
모범 답입니다.
while True:
raw = input('수량: ')
try:
count = int(raw)
except ValueError:
print('숫자만 됩니다')
continue
if 1 <= count <= 10:
break
print('1~10만 됩니다')
print('주문:', count)넣는 값세개03수량: 세개
숫자만 됩니다
수량: 0
1~10만 됩니다
수량: 3
주문: 3- 다르게 써도 되는 곳:
1 <= count <= 10은count >= 1 and count <= 10으로 써도 같습니다. - 흔한 오답:
except ValueError:안에continue를 빼먹으면'세개'를 넣었을 때count가 만들어지지 않은 채로if 1 <= count <= 10:으로 내려가NameError가 납니다.- 조건을
1 < count < 10으로 쓰면 경계 값인10(둘째 시험 값)이 거부됩니다.
다시 볼 레슨: 맞는 값이 올 때까지 다시 묻기 · try와 except · while과 추적 표