본문으로 건너뛰기

합 모으기와 세기

파이썬 목차반복레슨 20 / 59

목차

합 모으기는 이름 하나를 0에 붙여 두고, 반복에서 값을 하나씩 꺼낼 때마다 그 이름에 더해 가는 틀입니다. 세기는 조건이 맞을 때마다 1을 더하는 같은 틀입니다.

1부터 3까지의 합은 1 + 2 + 3으로 쓰면 됩니다. 그러나 1부터 100까지라면 식이 너무 길고, 범위가 바뀔 때마다 식을 다시 써야 합니다. 반복과 이름 하나로 쓰면 범위만 바꿔 같은 코드를 씁니다. 이 레슨은 반복으로 값을 모으는 코드를 직접 쓰는 틀 레슨입니다. 풀이 예제를 하는 일 셋으로 나눠 읽고, 빈칸을 채우며 쓰기로 넘어갑니다.

11단계 중 1단계. 합을 구하는 코드를 하위 목표 셋으로 나눠 따라갑니다.

1합 모으기의 세 하위 목표

1부터 3까지의 합을 구하는 풀이 예제입니다. 코드를 하는 일 셋으로 나누고 주석 머리줄(#)을 달았습니다. 이렇게 나눈 일 하나하나를 하위 목표(subgoal)라고 부릅니다.

# 1. 합을 0으로
total = 0
# 2. 하나씩 꺼내 더하기
for n in range(1, 4):
    total = total + n
# 3. 끝나고 쓰기
print(total)
실행 결과
6
  • 1. 합을 0으로: 반복 앞에서 total을 0에 붙입니다. 아직 아무것도 더하지 않은 합이 0입니다.
  • 2. 하나씩 꺼내 더하기: 5번 줄은 오른쪽을 먼저 계산합니다. 지금 total에 꺼낸 n을 더한 값을 만들고, 그 값에 total을 다시 붙입니다(규칙 2). 바퀴마다 total이 1, 3, 6으로 커집니다.
  • 3. 끝나고 쓰기: 반복이 다 끝난 뒤 한 번 찍습니다. 그래서 print(total)은 들여 쓰지 않습니다.

추적 표로 따라가면 total이 커지는 모습이 보입니다.

줄바뀐 이름값출력
2total0
4n1
5total1
4n2
5total3
4n3
5total6
4꺼낼 수 없음 — 반복 끝
76

n처럼 반복이 꺼낸 값을 차례로 받는 이름을 걸음꾼, total처럼 값을 모아 가는 이름을 모으는 값이라고 부릅니다. 이름마다 맡은 역할을 알면 처음 보는 코드도 빨리 읽힙니다. total = total + n은 total += n으로 줄여 쓸 수도 있습니다. 수에서는 뜻이 같습니다. 이 과목은 계산 차례가 잘 보이는 앞의 꼴로 씁니다.

2세기 — 맞으면 1 더하기

세기도 같은 틀입니다. 꺼낸 값을 더하는 대신 조건이 맞을 때만 1을 더합니다. 맞을 때마다 1을 더한 합이 곧 개수입니다. 1부터 10까지 가운데 3으로 나누어떨어지는 수를 셉니다. n % 3은 n을 3으로 나눈 나머지입니다.

# 1. 합을 0으로
count = 0
# 2. 하나씩 꺼내 맞으면 1 더하기
for n in range(1, 11):
    if n % 3 == 0:
        count = count + 1
# 3. 끝나고 쓰기
print(count)
실행 결과
3

n이 3, 6, 9일 때만 조건이 True라서 6번 줄이 세 번 실행됩니다. count도 모으는 값입니다. 하위 목표 셋의 짜임은 합 모으기와 같고, 2번 하위 목표 안에 조건 하나가 더 들었을 뿐입니다.

3print를 어디에 두는가

아래 두 코드는 마지막 줄의 들여쓰기만 다릅니다. 각각 무엇을 찍을까요? 답을 정한 뒤 펼쳐 보세요.

total = 0
for n in range(1, 4):
    total = total + n
    print(total)
실행 결과 보기
실행 결과
1
3
6
total = 0
for n in range(1, 4):
    total = total + n
print(total)
실행 결과 보기
실행 결과
6

예상과 다르면 그곳이 배울 곳입니다. 4번 줄을 들여 쓰면 덩어리에 들어가 바퀴마다 실행되고, 들여 쓰지 않으면 반복이 다 끝난 뒤 한 번 실행됩니다. 들여쓰기가 덩어리를 정합니다(규칙 4). 합을 한 번만 쓰려면 3번 하위 목표 '끝나고 쓰기'대로 반복 밖에 둡니다.

예제

1부터 100까지 더하기

1절 코드에서 범위만 range(1, 101)로 바꿨습니다. 101은 넣지 않으므로 1부터 100까지 더합니다.

total = 0
for n in range(1, 101):
    total = total + n
print(total)
실행 결과
5050

바퀴는 100번으로 늘었지만 코드는 그대로 네 줄입니다. 합 모으기 틀은 범위가 바뀌어도 같은 꼴로 씁니다.

합을 0으로 두지 않으면

1번 하위 목표를 빠뜨렸습니다.

for n in range(1, 4):
    total = total + n
print(total)
실행 결과
Traceback (most recent call last):  File "main.py", line 2, in <module>    total = total + n            ^^^^^NameError: name 'total' is not defined

맨 아래 줄부터 읽습니다. NameError는 그런 이름이 없다는 오류이고, total이 정의되지 않았다(not defined)는 뜻입니다. 2번 줄의 오른쪽 total + n을 계산하려는데, total은 아직 어떤 값에도 붙은 적이 없습니다. 오류는 2번 줄에서 났지만 고칠 곳은 반복 앞입니다. total = 0을 1번 줄에 넣습니다.

자주 틀리는 곳

틀린 생각: 이름이 total이면 파이썬이 알아서 값을 더해 합을 만든다.

total은 영어로 '합계'라서, 그 이름을 쓰면 값이 저절로 쌓일 것처럼 읽힙니다. 파이썬은 이름의 뜻을 모릅니다.

total = 0
for n in range(1, 4):
    total = n
print(total)
실행 결과
3

3번 줄은 바퀴마다 total을 그때 n이 가리키는 값에 다시 붙일 뿐이라, 마지막에 꺼낸 3만 남습니다.

맞는 규칙: 파이썬은 이름의 뜻을 모르고 쓴 식대로만 계산합니다. 더하려면 total = total + n처럼 더하는 식을 씁니다(규칙 6).

틀린 생각: print를 덩어리 안에 둬도 합은 한 번만 찍힌다.

print(total)이 반복 아래 마지막 줄에 있으니, 반복이 끝난 뒤 한 번 실행될 것처럼 보입니다. 그 줄이 어느 덩어리에 드는지는 자리가 아니라 들여쓰기가 정합니다.

3절에서 보았듯 4칸 들인 print(total)은 바퀴마다 실행되어 1, 3, 6을 찍습니다.

맞는 규칙: 4칸 들인 줄은 덩어리에 들어 바퀴마다 실행되고, 들여 쓰지 않은 줄은 반복이 끝난 뒤 한 번 실행됩니다. 합 하나를 쓰려면 print를 반복 밖에 둡니다(규칙 4).

틀린 생각: 합을 0으로 두는 줄은 덩어리 안에 둬도 한 번만 실행된다.

합을 0으로 두는 일은 처음에 한 번 하는 일이라, 어디에 두든 한 번만 실행될 것 같습니다. 덩어리 안의 줄은 바퀴마다 실행됩니다.

for n in range(1, 4):
    total = 0
    total = total + n
print(total)
실행 결과
3

바퀴마다 total을 0에 다시 붙여서 앞 바퀴까지 모은 값이 사라지고, 마지막 바퀴의 0 + 3만 남습니다.

맞는 규칙: 덩어리 안에서 0에 다시 붙이면 합이 바퀴마다 0부터 다시 시작합니다. 합을 0으로 두는 줄은 반복 앞에 들여 쓰지 않고 써서 한 번만 실행되게 합니다(규칙 4).

틀린 생각: 결과가 틀리면 코드를 눈으로 다시 읽는 수밖에 없다.

코드를 쓴 사람에게는 코드가 뜻한 대로 읽혀서, 눈으로만 보면 틀린 줄을 지나치기 쉽습니다. 바퀴마다 값을 찍게 하면 파이썬이 실제로 한 일이 보입니다.

아래는 3번 줄을 total = n으로 잘못 쓴 코드의 덩어리 안에 print(n, total)을 잠깐 넣은 것입니다.

total = 0
for n in range(1, 4):
    total = n
    print(n, total)
print(total)
실행 결과
1 1
2 2
3 3
3

찍어 보니 total이 늘 n과 같습니다. 3번 줄이 더하지 않고 다시 붙이기만 한다는 뜻입니다. 값을 찍어 보며 고치는 법은 뒤의 '값을 찍어 보며 고치기' 레슨에서 자세히 다룹니다.

맞는 규칙: 덩어리 안에 잠깐 넣은 print는 바퀴마다 실제 값을 찍어, 추적 표와 어긋나는 바퀴를 보여 줍니다. 틀린 곳을 고친 뒤에는 넣었던 print를 지웁니다.

확인 문제

1. 1절 풀이 예제의 range(1, 4)를 range(1, 5)로 바꿨습니다. 무엇이 찍히는지 쓰세요.

# 1. 합을 0으로
total = 0
# 2. 하나씩 꺼내 더하기
for n in range(1, 5):
    total = total + n
# 3. 끝나고 쓰기
print(total)
힌트

range(1, 5)가 내주는 수를 먼저 적고, 바퀴마다 total을 추적 표에 씁니다.

정답
실행 결과
10

range(1, 5)는 1, 2, 3, 4를 내줍니다. total은 0 → 1 → 3 → 6 → 10입니다.

흔한 오답은 15입니다. 끝 수 5도 든다고 본 것입니다(끝도 든다는 생각). range는 끝 수를 넣지 않습니다.

2. 빈칸을 채워 코드를 완성하세요.

(가) 1부터 5까지의 합 15가 찍히도록 한 줄의 빈칸을 채우세요.

# 1. 합을 0으로
total = 0
# 2. 하나씩 꺼내 더하기
for n in range(1, 6):
    total = ________
# 3. 끝나고 쓰기
print(total)
힌트

2번 하위 목표 '하나씩 꺼내 더하기'입니다.

정답

total + n입니다.

# 1. 합을 0으로
total = 0
# 2. 하나씩 꺼내 더하기
for n in range(1, 6):
    total = total + n
# 3. 끝나고 쓰기
print(total)
실행 결과
15

다르게 써도 되는 곳: n + total로 써도 같습니다.

빈칸에 15를 바로 써도 15가 찍히지만, 범위를 range(1, 11)로 바꾸면 55가 아니라 15가 그대로 찍힙니다. 합을 모으려면 꺼낸 n을 더해야 합니다.

흔한 오답은 n만 쓰는 것입니다. 이름이 total이면 파이썬이 알아서 더해 준다고 본 것입니다(이름이 뜻을 정한다는 생각). 그러면 바퀴마다 total이 그때 n의 값에 다시 붙기만 해서 마지막 값 5가 찍힙니다.

(나) 1부터 10까지 가운데 짝수의 개수를 세는 코드입니다. 2번 하위 목표를 통째로 채우세요. 다 채운 코드는 5를 찍어야 합니다(2, 4, 6, 8, 10).

# 1. 합을 0으로
count = 0
# 2. 하나씩 꺼내 맞으면 1 더하기

# 3. 끝나고 쓰기
print(count)
힌트

2절 세기 코드의 2번 하위 목표와 같은 세 줄입니다. 짝수는 2로 나눈 나머지가 0입니다.

정답
# 1. 합을 0으로
count = 0
# 2. 하나씩 꺼내 맞으면 1 더하기
for n in range(1, 11):
    if n % 2 == 0:
        count = count + 1
# 3. 끝나고 쓰기
print(count)
실행 결과
5

다르게 써도 되는 곳: 6번 줄은 count += 1로 써도 같습니다. 1은 짝수가 아니라서 4번 줄을 range(2, 11)로 써도 같은 5가 찍힙니다.

조건을 n % 2 == 1로 써도 5가 찍히지만, 이것은 홀수 1, 3, 5, 7, 9를 센 것입니다. 짝수는 2로 나눈 나머지가 0입니다.

흔한 오답은 6번 줄을 count = n으로 쓰는 것입니다. 이름이 count면 파이썬이 알아서 센다고 본 것입니다(이름이 뜻을 정한다는 생각). 마지막 짝수 10이 찍힙니다.

3. 사흘 동안 걸은 걸음 수의 합을 구하려 합니다. 날마다 1000걸음씩 늘려 1000, 2000, 3000걸음을 걸었으니 합은 6000이어야 하는데, 3000이 찍혔습니다. 몇 번 줄을 어떻게 고쳐야 할까요?

total = 0
for day in range(1, 4):
    steps = day * 1000
    total = steps
print(total)
실행 결과
3000
힌트

2번 하위 목표 '하나씩 꺼내 더하기'가 정말 더하고 있는지 봅니다.

정답

4번 줄을 total = total + steps⁠로 고칩니다.

total = 0
for day in range(1, 4):
    steps = day * 1000
    total = total + steps
print(total)
실행 결과
6000

고치기 전 4번 줄은 바퀴마다 total을 그날 걸음 수(steps가 가리키는 값)에 다시 붙일 뿐이라, 마지막 날의 3000만 남았습니다. 이름이 total이어도 파이썬은 알아서 더하지 않습니다(규칙 6).

다르게 고쳐도 되는 곳: 4번 줄을 total += steps나 total = total + day * 1000⁠으로 써도 6000이 찍힙니다. 3번 줄을 steps = total + day * 1000⁠으로 고쳐도 6000이 찍히지만, 그러면 steps가 그날 걸음 수가 아니라 그때까지의 합에 붙어 이름과 뜻이 어긋납니다.

흔한 오답은 5번 줄을 들여 쓰는 것입니다. 합 대신 3000이 찍힌 까닭이 찍는 5번 줄의 자리에 있다고 본 것입니다. 그러면 1000, 2000, 3000이 줄마다 찍힐 뿐 합은 구해지지 않습니다.

아래 코드의 8번 줄을 8칸 들여 if 덩어리에 넣으면 찍히는 줄을 모두 봅니다.

처음 펼 때 약 6MB를 받습니다.컴퓨터에서 해 보기

끝까지 내려오면 저절로 표시됩니다. 이 기기에만 저장합니다.

파이썬 목차로