[파이썬 100강] 08강. 함수 정의와 반환값 활용하기
함수(function)는 파이썬 코드를 “재사용 가능한 블록”으로 만드는 가장 중요한 도구입니다. 같은 계산, 같은 검증, 같은 출력 패턴을 매번 복붙하지 않고 이름을 붙여 호출하면 코드가 짧아지고 실수도 줄어듭니다. 특히 데이터 처리나 자동화 스크립트에서는 함수 설계가 품질을 거의 결정한다고 봐도 과장이 아닙니다.
이번 강의에서는 함수의 정의(def), 매개변수(parameter), 반환값(return), 그리고 실무에서 자주 부딪히는 실수를 한 번에 정리하겠습니다.
핵심 개념
함수는 입력을 받아 처리하고 결과를 돌려주는 단위입니다. 핵심은 아래 네 가지입니다.
- 정의(define):
def 함수명(...):형태로 만든다. - 호출(call):
함수명(...)으로 실행한다. - 매개변수(parameter): 함수가 받는 입력 규칙이다.
- 반환값(return value): 함수 실행 결과를 바깥으로 돌려준다.
코드를 길게 쓰는 것보다 작은 함수를 여러 개 만드는 습관이 디버깅과 테스트에 유리합니다.
>>> def greet(name):
... return f"안녕하세요, {name}님!"
...
>>> greet("건우")
'안녕하세요, 건우님!'
이 예제에서 name은 매개변수, '안녕하세요, 건우님!'은 반환값입니다.
기본 사용
1) 매개변수와 반환값이 있는 함수
>>> def calc_vat(price, rate=0.1):
... vat = price * rate
... total = price + vat
... return vat, total
...
>>> vat, total = calc_vat(50000)
>>> vat
5000.0
>>> total
55000.0
기본값 매개변수(rate=0.1)를 두면 호출 시 인자를 생략할 수 있어 API가 편해집니다.
2) 키워드 인자로 가독성 높이기
>>> def send_notice(user, title, urgent=False):
... level = "[긴급]" if urgent else "[일반]"
... return f"{level} {user}님 - {title}"
...
>>> send_notice(user="민지", title="배포 완료")
'[일반] 민지님 - 배포 완료'
>>> send_notice(title="DB 점검", user="서준", urgent=True)
'[긴급] 서준님 - DB 점검'
인자 순서를 헷갈리기 쉬운 함수에서는 키워드 인자가 실수를 크게 줄입니다.
3) 여러 값을 반환해서 후처리 분리하기
>>> def summarize_scores(scores):
... count = len(scores)
... total = sum(scores)
... avg = total / count if count else 0
... return count, total, round(avg, 2)
...
>>> n, s, a = summarize_scores([88, 92, 77, 95])
>>> print(n, s, a)
4 352 88.0
반환값을 잘 설계하면 출력/저장/전송 로직을 바깥에서 자유롭게 조합할 수 있습니다.
4) 실무형 예제: 주문 금액 계산기
>>> def checkout_amount(items, discount_rate=0.0, shipping_fee=3000):
... subtotal = sum(price for _, price in items)
... discount = subtotal * discount_rate
... final = subtotal - discount + shipping_fee
... return {
... "subtotal": subtotal,
... "discount": int(discount),
... "shipping_fee": shipping_fee,
... "final": int(final),
... }
...
>>> cart = [("키보드", 49000), ("마우스", 29000)]
>>> checkout_amount(cart, discount_rate=0.1)
{'subtotal': 78000, 'discount': 7800, 'shipping_fee': 3000, 'final': 73200}
딕셔너리로 반환하면 필드명이 살아 있어 후속 처리(영수증 출력, API 응답 생성)가 쉽습니다.
자주 하는 실수
실수 1) print()와 return을 혼동
>>> def add(a, b):
... print(a + b)
...
>>> result = add(3, 5)
8
>>> print(result)
None
print()는 화면에 보여줄 뿐이고, 함수 결과는 return으로 돌려줘야 변수에 담을 수 있습니다.
>>> def add(a, b):
... return a + b
...
>>> add(3, 5)
8
실수 2) 가변 기본값 사용 ([], {})
>>> def append_log(msg, logs=[]):
... logs.append(msg)
... return logs
...
>>> append_log("start")
['start']
>>> append_log("next")
['start', 'next']
호출마다 새 리스트가 아니라 같은 리스트가 재사용되어 버그가 납니다.
해결은 None을 기본값으로 두고 함수 안에서 새 객체를 만드는 방식입니다.
>>> def append_log(msg, logs=None):
... if logs is None:
... logs = []
... logs.append(msg)
... return logs
...
실수 3) 반환 타입이 상황마다 달라짐
어떤 경우엔 문자열, 어떤 경우엔 숫자를 반환하면 호출부에서 예외 처리가 복잡해집니다. 가능하면 같은 타입으로 일관되게 반환하세요.
실수 4) 함수가 너무 많은 일을 함
하나의 함수가 입력 검증, 계산, 출력, 파일 저장까지 모두 하면 테스트가 어려워집니다. “한 함수, 한 책임” 원칙으로 나누는 것이 유지보수에 훨씬 유리합니다.
오늘의 결론
함수는 단순 문법이 아니라 코드 설계 도구입니다.
- 매개변수와 반환값을 명확히 정의하면 재사용성이 올라간다.
print()는 출력,return은 결과 전달이라는 역할 차이를 구분한다.- 기본값은 편리하지만 가변 객체 기본값은 피한다.
- 함수는 작고 단일 책임으로 나눌수록 디버깅과 확장이 쉬워진다.
다음 강의(모듈과 표준 라이브러리)에서는 이렇게 만든 함수를 파일/모듈로 분리해 프로젝트 단위로 관리하는 방법을 배웁니다.
연습문제
- 두 수를 받아 큰 수를 반환하는 함수
max_of_two(a, b)를 작성하고,max_of_two(17, 42)결과를 확인해보세요. - 문자열 리스트를 받아 각 문자열 길이의 합을 반환하는 함수
total_length(words)를 작성해보세요. - 주문 목록
[("A", 12000), ("B", 8000), ("C", 5000)]을 입력받아 총액, 10% 할인액, 최종 결제액을 딕셔너리로 반환하는 함수를 작성해보세요.
이전 강의 정답 (07강 연습문제)
- 중복 제거 후 고유 사용자 수 출력
>>> users = ["kim", "lee", "kim", "park", "lee", "choi"]
>>> unique_users = set(users)
>>> unique_users
{'lee', 'park', 'kim', 'choi'}
>>> len(unique_users)
4
- 딕셔너리 순회 출력
>>> sales = {"mon": 120, "tue": 95, "wed": 132}
>>> for day, amount in sales.items():
... print(f"{day}:{amount}")
...
mon:120
tue:95
wed:132
- 교집합/차집합/합집합 계산
>>> a = {1, 2, 3, 4, 5}
>>> b = {4, 5, 6, 7}
>>> a & b
{4, 5}
>>> a - b
{1, 2, 3}
>>> a | b
{1, 2, 3, 4, 5, 6, 7}
실습 환경/재현 정보
- 실행 환경:
condaenvpython100(Python 3.11.14)