교재 홈: 바이브 코더를 위한 코딩 기초 학습

프로그래밍의 **함수(function)**는 특정 작업에 이름을 붙여 다시 사용할 수 있게 만든 코드 묶음입니다. 학교 수학의 함수나 그래프를 배웠다고 가정하지 않습니다. ‘재료를 받아 정해진 일을 하고 결과를 돌려주는 작은 작업’으로 시작하면 됩니다. 그 이름을 써서 작업을 시키는 것을 **호출(call)**이라고 합니다. 이 장에서는 계산 결과를 화면에 표시하는 일과 다음 코드로 돌려주는 일을 구분합니다.

매개변수와 인수, 반환값

평균은 여러 값을 모두 더한 뒤 값의 개수로 나눈 것입니다. 30분·45분·0분은 모두 더하면 75분이고, 기록이 3개이므로 75를 3으로 나눈 25분이 평균입니다. 0분도 실제로 적힌 기록 하나이므로 개수에 포함합니다. 0분·0분의 평균은 0분이지만, 기록이 하나도 없으면 나눌 개수도 없어 같은 계산을 할 수 없습니다.

아래 함수 이름 mean_minutes는 ‘평균 시간’, 입력 이름 values는 ‘값 목록’을 뜻합니다. len(values)는 목록의 값 개수, sum(values)는 모두 더한 합계를 구합니다. if len(values) == 0은 목록이 비어 있는지 묻습니다. 이름의 뜻과 계산 순서를 알면 코드를 따라갈 수 있습니다.

analysis.py에 다음 코드를 저장합니다.

def mean_minutes(values):
    if len(values) == 0:
        return None
    return sum(values) / len(values)

함수를 정의한다는 것은 함수의 이름과 수행할 일을 적는 것입니다. def가 그 시작이고, 괄호의 values는 값을 받을 자리인 **매개변수(parameter)**입니다. mean_minutes([30, 45, 0])처럼 호출할 때 실제로 건네는 값은 **인수(argument)**입니다. return 뒤의 값은 호출한 곳이 받는 **반환값(return value)**입니다. return을 실행하면 그 함수 호출은 끝납니다.

이 함수는 입력 목록에 계산 가능한 숫자가 들어 있다고 가정합니다. 입력을 검증한다는 것은 값의 종류와 범위를 정한 규칙과 대조하는 것입니다. 어떤 검증이 필요한지 정하고 테스트하는 과정은 08. 테스트와 검증 — ‘맞다’의 기준을 코드 밖에서 정하기의 「정상·경계·실패 사례」절에서 배웁니다. 지금 함수만으로 모든 잘못된 입력을 친절하게 처리하는 것은 아닙니다.

빈 목록의 평균은 이 교재에서 None으로 정했습니다. 평균 0은 실제 값들이 0인 경우에도 나올 수 있으므로 ‘계산할 관측값이 없음’과 구별하기 위해서입니다. 이것은 Python이 강제하는 유일한 규칙이 아니라 교재의 설계 결정입니다.

functions_demo.py에 저장합니다.

from analysis import mean_minutes

result = mean_minutes([30, 45, 0])
print(result)
print(mean_minutes([]))

python functions_demo.py의 출력은 25.0과 None입니다. 두 파일은 같은 폴더에 둡니다. analysis.py가 모듈(module)이 되고, from ... import ...가 그 안의 함수를 가져옵니다.

print와 return은 다릅니다

def show_total(values):
    print(sum(values))

result = show_total([10, 20])
print(result)

출력은 30 다음 None입니다. 화면에 30을 보여 주었지만 명시적인 return이 없어서 함수의 반환값은 None입니다. 이 값을 다시 더하려 하면 문제가 납니다. 계산 함수는 결과를 반환하고, 화면 출력은 호출한 쪽에서 담당하게 하면 테스트와 재사용이 쉬워집니다.

return 뒤의 같은 실행 경로는 더 이상 실행되지 않습니다. 반복문 안에 실수로 return을 넣으면 첫 원소만 처리하고 끝날 수 있습니다. AI가 만든 함수를 읽을 때에는 모든 반환 지점과 그 조건을 표시해 봅니다.

스코프와 부작용

**스코프(scope)**는 코드에서 이름을 사용할 수 있는 범위입니다. 함수 안에서 만든 이름을 **지역변수(local variable)**라고 하며, 보통 그 함수 안에서 사용합니다. 함수 밖에 둔 이름을 **전역변수(global variable)**라고 부릅니다. 함수가 바깥 값을 읽으면 괄호 안에 건넨 값이 같아도 바깥 값의 변화로 결과가 달라질 수 있습니다. 이렇게 실행 도중 유지되는 현재 값을 **상태(state)**라고 하며 05. 실행 구조 — 어디서 시작해 무엇이 바뀌는가에서 자세히 추적합니다.