Devin.KR

받은 코드 읽기 - 처음 보는 코드를 한 줄씩 따라가기

개발자KR 조회 0

이 장에서 배우는 것

앞 장에서 목적·입력·출력·예시를 담아 AI에게 프로그램을 요청했다. 이제 답으로 받은 코드를 읽을 차례다. 실행 결과가 요청한 모습과 비슷하더라도, 어떤 입력을 어떻게 처리했는지 설명할 수 있어야 한다. 그래야 다음 요청에서 바꿀 부분을 짚을 수 있다.

처음부터 모든 문법을 외울 필요는 없다. 값이 어디에 담기고, 어떤 조건에서 길이 갈라지며, 무엇을 되풀이하는지부터 살핀다. 이 장에서는 짧은 합계 함수를 읽고, 실행 중 달라지는 값을 표로 남기는 프로그램을 만든다. AI의 설명도 그 표와 실제 출력에 맞춰 확인한다.

  • 변수·조건·반복·함수가 코드에서 맡은 일을 읽는다.
  • 실행 순서를 따라가며 바뀐 값을 손으로 적는다.
  • print를 넣어 예상한 값과 실제 값을 비교한다.
  • AI가 설명한 실행 과정을 직접 기록한 표와 대조한다.
  • 짧은 함수의 실행 과정을 출력하는 추적기를 완성한다.

문제 상황

작은 모임에서 하루 동안 완료한 작업 수를 합치려 한다. 자료에는 2, 0, 3이 들어 있다. 양수는 합계에 더하고, 0 이하는 더하지 않기로 했다. AI에게 요청했더니 반복문과 조건문이 들어 있는 짧은 함수가 돌아왔다. 실행하면 5가 나온다.

여기서 “5가 나왔으니 됐다”라고 끝내면 코드를 읽는 연습이 되지 않는다. 0은 정말 건너뛰었는지, 3을 처리하기 직전의 합계가 얼마였는지, 마지막에 화면으로 보낸 값과 함수가 돌려준 값이 같은지 살펴봐야 한다. 입력을 바꿨을 때 어느 부분이 영향을 받는지도 알아야 한다.

AI에게 다음과 같이 설명을 요청했다고 가정한다.

이 함수에 [2, 0, 3]을 넣었을 때 실행되는 순서를 설명해 줘. 반복할 때마다 number와 total의 값을 적고, 조건을 확인하는 시점과 값을 더한 뒤의 시점을 구분해 줘. 코드는 바꾸지 말고 설명만 해 줘.

설명에 “3을 더하기 전 total은 5다”라는 문장이 들어 있다면 어떻게 판단해야 할까. 문장이 자연스러운지는 판단 근거가 되지 않는다. 직접 따라가 보면 3을 더하기 전 합계는 2이고, 더한 뒤에 5가 된다. 같은 변수라도 어느 시점의 값인지 구분해야 한다.

이번에 만드는 추적기는 이런 시점 차이를 드러낸다. 추적기란 실행 중의 진행 상황이나 값을 남겨 살펴보게 하는 프로그램이다. 여기서는 복잡한 자동 추적 기능 없이, 우리가 확인하려는 위치에 기록하는 코드를 직접 넣는다.

코드를 읽는 데 필요한 네 가지 문법

변수는 이름으로 값을 다시 찾는 수단이다

변수(variable)는 값에 붙여 사용하는 이름이다. 다음 코드는 total이라는 이름으로 0을 사용하다가, 계산한 새 값 2를 다시 total에 담는다.

total = 0
total = total + 2
print(total)

등호 하나인 =는 오른쪽 결과를 왼쪽 이름에 대입한다는 뜻이다. 수학에서 두 식이 같다고 선언하는 등호와 읽는 방법이 다르다. 두 번째 줄에서는 오른쪽의 기존 total 값 0으로 계산을 마친 다음, 왼쪽 total이 새 값 2를 가리키게 된다.

total += 2도 이 예제에서는 total = total + 2와 같은 결과를 낸다. +=를 보면 “현재 값에 오른쪽 값을 더해 다시 담는다”라고 읽으면 된다. 변수 이름만으로 역할을 단정하지는 않는다. 실제 대입과 사용 위치를 함께 살핀다.

[2, 0, 3]은 여러 값을 순서대로 담은 리스트(list)다. 대괄호 안의 값은 쉼표로 구분한다. 이번 프로그램은 리스트에서 값을 하나씩 꺼내 합계를 계산한다. 읽기를 시작할 때는 리스트 전체를 한꺼번에 더한다고 생각하지 말고, 지금 어떤 값 하나를 다루는지 표시한다.

조건은 실행할 갈래를 고른다

조건문은 판단 결과에 따라 실행할 부분을 고른다. if number > 0:은 “number가 0보다 크면 아래의 들여쓴 부분을 실행한다”라는 뜻이다. else: 아래는 그 조건이 맞지 않을 때 실행한다.

number = 0
total = 2

if number > 0:
    total += number
else:
    print("이번 값은 더하지 않는다")

print(total)

여기서는 number가 0이므로 조건이 맞지 않는다. 따라서 덧셈 줄은 실행하지 않고 안내 문장을 출력한다. 마지막 total은 여전히 2다. 조건에서 >는 ‘크다’, >=는 ‘크거나 같다’를 뜻한다. 두 기호를 바꾸면 0을 처리할 때 고르는 갈래가 달라진다.

콜론 : 뒤의 들여쓰기는 함께 실행할 코드의 범위를 나타낸다. 이 책의 예제는 공백 네 칸을 사용한다. 마지막 print(total)은 if와 같은 높이에서 시작하므로, 어느 갈래를 골랐든 그 뒤에 실행한다. 들여쓰기는 보기 좋게 꾸미는 장치에 그치지 않는다.

반복은 되돌아가고, 함수는 호출할 때 들어간다

반복문은 같은 코드 묶음을 여러 번 실행한다. for number in numbers:는 numbers에서 값을 하나씩 꺼내 number라는 이름으로 사용한다. [2, 0, 3]이라면 number는 차례로 2, 0, 3이 된다. 각 값에 대해 들여쓴 묶음을 끝까지 실행한 다음, 다음 값을 꺼낸다.

함수(function)는 이름을 붙여 두고 필요할 때 호출하는 코드 묶음이다. def로 정의하며, 괄호 안에는 함수가 받을 값의 이름을 적는다. 호출은 그 이름 뒤에 괄호를 붙여 실행을 요청하는 일이다.

def add_positive(numbers):
    total = 0
    for number in numbers:
        if number > 0:
            total += number
    return total


answer = add_positive([2, 0, 3])
print(answer)

def를 읽었다고 함수 안의 덧셈이 곧바로 실행되지는 않는다. 아래의 add_positive([2, 0, 3])을 만났을 때 함수 안으로 들어간다. 전달한 리스트는 함수 안에서 numbers라는 이름으로 사용한다. 이렇게 정의에 적힌 입력 이름을 매개변수라고 한다.

return은 함수 실행을 끝내고 값을 호출한 곳으로 돌려준다. 위 코드에서는 돌려준 5가 answer에 담긴다. print는 값을 화면에 보이고, return은 값을 호출한 곳으로 전달한다. 화면에 나온 숫자와 함수가 돌려준 숫자는 서로 다른 경로로 확인하는 대상이다.

처음 보는 코드에서 먼저 찾을 표시
표시읽는 말확인할 점
=오른쪽 값을 왼쪽 이름에 담는다대입 뒤 값이 무엇인가
if / else조건에 맞는 갈래를 실행한다실제로 어느 갈래를 택하는가
for값을 하나씩 꺼내 되풀이한다현재 값과 반복 범위는 무엇인가
def / return함수를 정의하고 값을 돌려준다언제 호출하며 무엇을 돌려주는가

위에서 아래로 읽되 실행 순서를 따라간다

코드는 기본적으로 위에서 아래로 진행하지만, 모든 줄을 한 번씩만 실행하는 것은 아니다. 함수 호출에서는 함수 안으로 들어갔다가 돌아오고, 반복문에서는 같은 묶음으로 되돌아간다. 조건이 맞지 않는 갈래는 지나친다. 따라서 코드가 적힌 순서와 실제 실행 경로를 함께 봐야 한다.

손 추적은 컴퓨터 대신 자신이 실행 순서를 따라가며 값을 적어 보는 방법이다. 종이나 메모장에 현재 number와 total을 적는다. 대입이 실행될 때마다 기존 값을 지우거나 새 행을 만들어 바뀐 값을 기록한다. 머릿속으로만 계산하면 ‘더하기 전’과 ‘더한 뒤’를 섞기 쉽다.

반복문은 값을 하나씩 꺼내 조건에 맞는 갈래를 실행한 뒤 다음 값으로 돌아간다

입력이 [2, 0, 3]일 때는 다음 표처럼 적을 수 있다. 표의 ‘현재 값 없음’은 아직 반복을 시작하지 않았거나 반복을 마친 시점을 뜻한다. total이 바뀌는 행에 특히 주목한다.

양수만 더하는 함수의 손 추적
시점numbertotal읽은 내용
초기화 뒤현재 값 없음0합계를 0으로 시작한다
첫 덧셈 뒤222는 양수이므로 더한다
둘째 값 처리 뒤02조건이 맞지 않아 유지한다
셋째 덧셈 뒤35기존 합계 2에 3을 더한다
반환 직전현재 값 없음5합계 5를 돌려준다

여기서 “0을 더해도 결과는 같으니 조건문은 상관없다”라고 판단하면 실행 경로를 놓친다. 이번 입력에서는 합계만으로 두 갈래를 구분하기 어렵다. 음수를 입력하면 차이가 드러난다. 조건문이 하는 일을 확인하려면 결과뿐 아니라 어떤 줄이 실행됐는지도 보아야 한다.

손 추적을 마치면 AI의 설명과 한 행씩 대조한다. “반복할 때 합계가 늘어난다”라는 설명은 너무 넓다. 0을 다룰 때 합계는 늘어나지 않는다. 설명을 검토할 때는 ‘항상’, ‘매번’ 같은 말이 실제 모든 행에 들어맞는지 살핀다.

print로 예상과 실제를 맞춰 본다

print는 괄호 안의 값을 화면에 출력한다. 여러 값을 쉼표로 나누면 기본적으로 사이에 공백을 넣어 출력한다. 확인하려는 줄의 앞뒤에 넣으면 같은 변수의 시점별 값을 볼 수 있다.

number = 3
total = 2
print("더하기 전", number, total)
total += number
print("더한 뒤", number, total)

이 코드를 실행하면 첫 줄에는 ‘더하기 전 3 2’, 다음 줄에는 ‘더한 뒤 3 5’가 나온다. 값만 출력하기보다 어떤 시점인지 함께 적으면 긴 출력에서도 구분하기 쉽다. 출력 위치를 덧셈 앞에 둘지 뒤에 둘지가 관찰하는 내용을 결정한다.

여러 지점을 비교할 때는 화면에 바로 흩어 출력하는 대신 기록을 모아 마지막에 표로 보여 줄 수 있다. 완성 코드에서는 record라는 함수가 그 일을 맡는다. record는 특별한 Python 명령이 아니라 우리가 붙인 이름이다. 호출한 순간의 위치, 현재 값, 합계를 한 행으로 저장한다.

같은 덧셈이라도 기록을 앞에 두면 이전 값이 남고 뒤에 두면 바뀐 값이 남는다

AI에게 코드를 고쳐 달라고 할 때는 변경 범위를 좁혀 말한다. 다음 요청문은 계산 규칙을 유지하면서 확인할 자리를 드러내게 한다.

양수만 더하는 규칙을 유지하면서 기록 함수를 추가해 줘. 초기화 뒤, 각 값을 꺼낸 직후, 더하거나 건너뛴 뒤, 반환 직전에 기록해 줘. 단계·위치·number·total을 표로 출력하고, 자동 실행 추적 기능은 쓰지 마. 기존 코드와 달라진 부분도 설명해 줘.

응답을 받으면 변경 전후 차이(diff)를 검토한다. 차이 검토란 이전 코드와 새 코드에서 추가·삭제·수정된 부분을 비교하는 일이다. 조건이 >에서 >=로 바뀌지 않았는지, total을 0으로 만드는 줄이 반복문 안으로 이동하지 않았는지, return의 위치가 그대로인지 살핀다.

추적 코드를 넣는 일도 프로그램을 수정하는 일이다. 기록을 추가했으니 계산은 그대로일 것이라고 가정하지 않는다. 손으로 구한 결과 5와 실행 결과를 비교하고, 표의 중간 값까지 맞는지 확인한다. 다만 이 한 입력의 일치는 이 입력에서 관찰한 동작을 확인해 줄 뿐이다.

완성 코드

다음 코드를 main.py로 저장한다. 외부 파일이나 추가 설치 없이 실행된다. 기록은 리스트에 모으며, 현재 값이 없는 시작과 반환 시점에는 문자열 "-"를 넣는다. 이 표시는 number 변수의 실제 값을 바꾸지 않고, 표에서 그 칸을 어떻게 보여 줄지만 정한다.

def record(rows, location, number, total):
    step = len(rows) + 1
    row = (step, location, number, total)
    rows.append(row)


def add_positive(numbers, rows):
    total = 0
    record(rows, "시작", "-", total)

    for number in numbers:
        record(rows, "반복", number, total)
        if number > 0:
            total += number
            record(rows, "더함", number, total)
        else:
            record(rows, "건너뜀", number, total)

    record(rows, "반환", "-", total)
    return total


def show_trace(rows):
    print("단계 | 위치 | number | total")
    print("--- | --- | --- | ---")
    for row in rows:
        step, location, number, total = row
        print(f"{step} | {location} | {number} | {total}")


def main():
    numbers = [2, 0, 3]
    rows = []
    expected = 5

    result = add_positive(numbers, rows)

    print("입력:", numbers)
    show_trace(rows)
    print("계산 결과:", result)
    print("기대 결과:", expected)
    print("결과 일치:", result == expected)


if __name__ == "__main__":
    main()

이 프로그램은 46줄이며 빈 줄도 포함한 길이다. sys.settrace 같은 자동 추적 기능을 사용하지 않는다. 기록을 호출한 위치만 표에 나타나므로, 모든 Python 줄이 표의 한 행과 대응하는 것은 아니다. 표의 단계 번호는 소스 코드의 줄 번호가 아니라 기록한 순서다.

줄별 해설

위 코드의 첫 줄을 1번으로 세며 빈 줄도 줄 수에 포함한다. 줄 번호를 코드에 직접 붙여 저장하지는 않는다. 먼저 함수의 역할을 훑은 다음, 실제 실행이 시작되는 맨 아래에서 main으로 들어가 호출을 따라 읽는다.

완성 코드의 모든 줄이 맡은 일
줄내용읽는 방법
1record 정의기록 목록과 세 가지 관찰 값을 받는다.
2단계 계산len으로 현재 기록 개수를 구하고 1을 더한다.
3행 만들기네 값을 괄호로 묶어 한 행으로 만든다.
4행 추가append로 rows의 끝에 행 하나를 붙인다.
5~6빈 줄함수 사이를 구분하며 계산에는 관여하지 않는다.
7계산 함수 정의계산할 목록과 기록을 담을 목록을 받는다.
8초기화함수를 호출할 때 합계가 0에서 시작한다.
9시작 기록반복에 들어가기 전 합계 0을 남긴다.
10빈 줄초기화와 반복 부분을 구분한다.
11반복 시작numbers의 값을 차례로 number에 담는다.
12반복 기록현재 값을 처리하기 전 합계를 남긴다.
13조건 확인현재 값이 0보다 큰지 판단한다.
14합계 변경조건이 맞을 때만 현재 값을 더한다.
15변경 뒤 기록덧셈을 마친 합계를 남긴다.
16다른 갈래조건이 맞지 않으면 이 아래를 실행한다.
17유지 기록합계를 바꾸지 않고 현재 상태를 남긴다.
18빈 줄반복 부분과 반환 부분을 구분한다.
19반환 기록반복을 모두 마친 합계를 남긴다.
20값 반환total을 호출한 곳으로 돌려준다.
21~22빈 줄다음 함수와 구분한다.
23표 출력 함수 정의쌓인 기록을 화면에 보이는 일을 맡는다.
24~25표 머리 출력열 이름과 구분선을 출력한다.
26기록 순회저장한 행을 앞에서부터 하나씩 꺼낸다.
27행 풀기행의 네 값을 왼쪽의 네 이름에 순서대로 담는다.
28한 행 출력문자열의 중괄호 자리에 각 값을 넣는다.
29~30빈 줄출력 함수와 main을 구분한다.
31main 정의입력 준비부터 결과 확인까지 묶는다.
32입력 준비처리할 세 숫자를 리스트에 담는다.
33빈 기록 목록[]로 아무 행도 없는 리스트를 만든다.
34기대값 준비손으로 계산한 예상 결과 5를 담는다.
35빈 줄준비와 실행을 구분한다.
36계산 호출돌려받은 합계를 result에 담는다.
37빈 줄계산과 화면 출력을 구분한다.
38~41결과 출력입력, 기록 표, 실제 결과, 기대 결과를 보인다.
42일치 여부 출력==로 두 값이 같은지 비교한다.
43~44빈 줄함수 정의와 시작 부분을 구분한다.
45~46실행 시작이 파일을 직접 실행하면 main을 호출한다.

3줄의 괄호로 묶은 값은 튜플(tuple)이다. 여기서는 한 행의 네 값을 함께 보관하는 묶음으로 이해하면 된다. 바깥의 rows는 행을 계속 추가할 리스트이고, 그 안에 각 행의 튜플이 들어간다. 27줄은 행에 담긴 순서대로 네 값을 꺼내 이름을 붙이는 코드다.

rows.append(row)는 rows 목록 자체에 행을 추가한다. main에서 만든 목록을 계산 함수와 기록 함수에 전달했으므로, 계산이 끝난 뒤에도 main에서 그 기록을 볼 수 있다. 반면 total은 계산 함수 안에서 사용하는 이름이다. main은 반환받은 값을 result라는 이름으로 사용한다.

28줄의 f로 시작하는 문자열은 중괄호 안의 값을 글자 사이에 끼워 넣는다. 예를 들어 step이 1이면 {step} 자리에 1이 표시된다. 세로선 |은 계산 기호가 아니라 열 사이를 구분하기 위해 넣은 글자다.

42줄의 ==는 같음을 비교한다. 같으면 True, 다르면 False가 된다. True와 False는 각각 참과 거짓을 나타내는 값이다. 이번 출력에서 True는 최종 합계가 기대값과 같다는 뜻이며, 기록한 모든 중간 값까지 자동으로 검사했다는 뜻은 아니다.

45줄의 __name__과 "__main__"은 파일을 직접 실행했을 때 시작 함수를 부르기 위해 사용하는 형태다. 지금은 그 아래 main()으로 실행이 들어간다고 읽으면 된다. 프로그램의 흐름은 main에서 계산 함수로, 계산 함수에서 기록 함수로 들어갔다가 차례로 돌아온다.

실행 결과

main.py가 들어 있는 폴더에서 터미널에 다음 명령을 입력한다.

python3 main.py

예상 출력은 다음과 같다.

입력: [2, 0, 3]
단계 | 위치 | number | total
--- | --- | --- | ---
1 | 시작 | - | 0
2 | 반복 | 2 | 0
3 | 더함 | 2 | 2
4 | 반복 | 0 | 2
5 | 건너뜀 | 0 | 2
6 | 반복 | 3 | 2
7 | 더함 | 3 | 5
8 | 반환 | - | 5
계산 결과: 5
기대 결과: 5
결과 일치: True

2단계와 3단계를 나란히 보면 number는 2로 같고 total만 0에서 2로 바뀐다. 4단계와 5단계에서는 두 값이 모두 유지된다. 6단계의 total은 2이고, 7단계에서 5가 된다. 문제 상황에 나온 AI의 설명은 이 두 시점을 혼동한 셈이다.

설명이 실행과 다르면 관찰한 행을 붙여 다시 요청한다. 막연히 “설명이 이상하다”라고 말하기보다, 어떤 값의 어느 시점이 다른지 보여 주는 편이 좋다.

설명에서는 3을 더하기 전 total이 5라고 했지만, 실행 표의 6단계는 number가 3이고 total이 2다. 7단계에서 total이 5가 된다. 더하기 전과 뒤를 구분해 설명을 수정해 줘. 계산 코드는 유지해 줘.

수정된 설명도 표와 대조한다. 설명만 고치도록 요청했는데 코드까지 돌아왔다면, 기존 파일을 바로 덮어쓰기 전에 달라진 부분을 살핀다. 읽기 연습에서는 설명을 얻는 일과 실행으로 확인하는 일을 한 쌍으로 반복한다.

실무에서 자주 틀리는 것

합계를 반복할 때마다 0으로 만든다

다음 코드는 실행되지만 결과가 3이다. total = 0이 반복문 안에 있어 새 숫자를 꺼낼 때마다 이전 합계를 없애기 때문이다.

total = 0
for number in [2, 0, 3]:
    total = 0
    if number > 0:
        total += number
print(total)

합계의 시작값은 반복 전에 한 번만 정한다. 고친 코드에서는 2를 처리한 결과가 다음 반복까지 이어진다.

total = 0
for number in [2, 0, 3]:
    if number > 0:
        total += number
print(total)

기록을 앞에 두고 변경 뒤의 값으로 읽는다

다음 코드는 ‘더한 뒤’라고 출력하지만 실제로는 더하기 전 값 2를 보여 준다. 문구가 실행 시점을 바꿔 주지는 않는다.

total = 2
number = 3
print("더한 뒤:", total)
total += number

변경 뒤의 값을 확인하려면 출력도 변경 뒤로 옮긴다. 계산 줄은 그대로이고 출력 위치만 바뀌었는지 비교한다.

total = 2
number = 3
total += number
print("더한 뒤:", total)

첫 값만 처리하고 함수를 끝낸다

다음 함수는 return이 반복문 안에 있다. 첫 값 2를 처리하고 곧바로 함수를 끝내므로 결과는 2다. 코드의 마지막에 가까이 적혔더라도 들여쓰기를 먼저 확인해야 한다.

def add_positive(numbers):
    total = 0
    for number in numbers:
        if number > 0:
            total += number
        return total


print(add_positive([2, 0, 3]))

모든 값을 처리한 뒤 반환하려면 return을 반복문 밖으로 옮긴다. 다음 코드는 5를 출력한다.

def add_positive(numbers):
    total = 0
    for number in numbers:
        if number > 0:
            total += number
    return total


print(add_positive([2, 0, 3]))

화면에 출력한 것을 반환한 값으로 생각한다

다음 코드는 함수 안에서 5를 출력하지만 값을 반환하는 return은 없다. 이런 함수의 호출 결과는 None이다. None은 여기서 돌려받은 계산 값이 없음을 나타낸다. 따라서 화면에는 5 다음에 ‘받은 값: None’이 나온다.

def add_two(a, b):
    print(a + b)


answer = add_two(2, 3)
print("받은 값:", answer)

호출한 곳에서 값을 사용하려면 return으로 돌려준다. 이제 answer에 5가 담기며 ‘받은 값: 5’가 출력된다.

def add_two(a, b):
    return a + b


answer = add_two(2, 3)
print("받은 값:", answer)

한눈에 보기

받은 코드를 읽고 확인하는 순서
할 일살필 대상확인 방법
시작점 찾기main 호출과 함수 호출어느 함수에 들어갔다 돌아오는지 표시한다.
값 따라가기대입과 덧셈실행 뒤의 값을 새 행에 적는다.
갈래 고르기조건과 들여쓰기입력값으로 조건을 직접 판단한다.
반복 읽기현재 값과 누적 값현재 값이 바뀌어도 합계는 이어지는지 본다.
실행 관찰하기print와 기록 위치변경 전인지 뒤인지 출력 문구와 맞춘다.
AI 설명 검토하기주장한 값과 실행 순서실제 표의 행을 근거로 대조한다.
수정 확인하기기존 코드와 새 코드의 차이기록 추가 외에 계산 규칙도 바뀌었는지 본다.

연습 문제

  1. 완성 코드의 입력을 [4, -2, 1]로, 기대 결과를 5로 바꾼다고 하자. 실행 전에 기록의 각 행을 손으로 적는다. 건너뜀 행의 number와 total은 각각 얼마인지 구한다.
  2. 완성 코드에서 조건만 number >= 0으로 바꾼다고 하자. 원래 입력 [2, 0, 3]에서 최종 합계와 5단계의 위치 이름이 어떻게 되는지 예상한다. 실행 결과로 확인하고 변경 전후 한 줄을 비교한다.
  3. 완성 코드에서 numbers를 빈 리스트 []로, expected를 0으로 바꾼다. 기록이 몇 행 생기며 어떤 위치가 기록되는지 실행 전에 예상한다.
  4. AI가 “시작과 반환 행의 number가 '-'이므로, 함수는 반환 전에 number를 '-'로 바꾼다”라고 설명했다. 이 설명이 맞는지 코드의 전달 값을 근거로 판단하고, 실제 number를 확인할 print를 어디에 넣을지 정한다.

정답과 해설

  1. 기록은 여덟 행이다. 순서대로 ‘시작, -, 0’, ‘반복, 4, 0’, ‘더함, 4, 4’, ‘반복, -2, 4’, ‘건너뜀, -2, 4’, ‘반복, 1, 4’, ‘더함, 1, 5’, ‘반환, -, 5’가 된다. 건너뜀 행의 number는 -2이고 total은 4다. 음수를 빼는 계산을 한 것이 아니라 덧셈 줄을 실행하지 않은 것이다.

  2. 최종 합계는 그대로 5이고 5단계의 위치 이름은 ‘더함’이 된다. 0도 조건에 맞아 덧셈 갈래로 들어가지만, 0을 더하므로 합계는 유지된다. 결과 숫자가 같더라도 실행 경로는 달라질 수 있음을 보여 준다. 변경 전의 >와 변경 후의 >=를 비교하면 갈래가 달라진 이유를 찾을 수 있다.

  3. 두 행이 생긴다. 첫 행은 ‘시작, -, 0’, 둘째 행은 ‘반환, -, 0’이다. 꺼낼 값이 없으므로 반복문 안의 코드는 한 번도 실행되지 않는다. total의 초기화와 반환 기록은 반복문 밖에 있으므로 실행된다. 계산 결과와 기대 결과는 모두 0이다.

  4. 설명은 맞지 않는다. record를 호출할 때 세 번째 값으로 문자열 "-"를 직접 전달했을 뿐, 계산 함수의 number에 대입하지 않았다. 원래 입력을 사용한 상태에서 반환 기록 바로 앞에 다음 출력을 넣으면 마지막 반복값 3을 확인할 수 있다. 해당 줄은 계산 함수 안에서 return과 같은 높이로 들여쓴다.

    print("마지막 반복값:", number)

    이 확인 줄은 원래의 비어 있지 않은 입력을 전제로 한다. 빈 리스트에서는 반복문이 number에 값을 한 번도 담지 않으므로 그대로 사용할 수 없다. 확인을 마치면 추가한 줄을 제거하고 완성 코드의 출력으로 돌아오는지 비교한다.

받은 코드를 읽는다는 것은 이름과 문법을 알아보는 데서 한 걸음 더 나아가는 일이다. 입력 하나를 정하고, 실행 경로를 따라 값을 적고, 관찰한 출력과 맞춘다. 예상과 다른 지점을 찾았다면 그 위치와 값을 남긴다. 다음 장에서는 실행이 멈추며 나타나는 오류 메시지에서 그 단서를 읽는 방법을 다룬다.

댓글 0

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

댓글을 남기려면 로그인이 필요합니다.