프로그램을 조금만 길게 써 보면 금방 이런 순간이 옵니다.
'어? 아까 쓴 코드랑 거의 똑같은데?'
처음에는 복사해서 붙여 넣으면 빨라 보입니다. 하지만 프로그램이 커질수록 같은 코드가 여기저기 흩어지고, 하나를 고치면 다른 곳도 같이 고쳐야 하는 일이 생깁니다. 이럴 때 코드를 깔끔하게 정리해 주는 도구가 바로 함수입니다.
함수는 특정 일을 맡는 작은 기계라고 생각하면 쉽습니다. 이름을 붙여 두고, 필요할 때마다 불러서 쓰면 됩니다. 이미 우리는 print(), input(), len(), sum() 같은 내장 함수들을 사용해 왔습니다. 이런 함수들은 파이썬에 기본으로 들어 있어 언제든 바로 쓸 수 있습니다.1
이번에는 한 걸음 더 나아가, 우리가 직접 함수를 만들어 보겠습니다.
왜 함수가 필요할까
함수의 가장 큰 장점은 같은 코드를 반복하지 않게 해 준다는 점입니다. 하지만 장점은 그것만이 아닙니다.
재사용하기 쉽습니다. 한 번 만들어 두면 여러 번 부를 수 있습니다.
읽기 쉬워집니다. 긴 코드를 작은 의미 단위로 나눌 수 있습니다.
고치기 쉬워집니다. 수정할 곳이 한 군데로 모입니다.
예를 들어 상품 가격에 10% 할인을 적용하는 코드가 여러 번 나온다고 해 봅시다.
price1 = 12000
final1 = price1 * 0.9
print(final1)
price2 = 34000
final2 = price2 * 0.9
print(final2)
price3 = 5000
final3 = price3 * 0.9
print(final3)지금은 줄 수가 적어서 괜찮아 보입니다. 하지만 할인율이 바뀌면 세 군데를 모두 수정해야 합니다.
함수로 바꾸면 이렇게 됩니다.
def get_discount_price(price):
return price * 0.9
print(get_discount_price(12000))
print(get_discount_price(34000))
print(get_discount_price(5000))이제 할인 계산 규칙은 get_discount_price() 안에만 들어 있습니다. 프로그램이 더 길어질수록 이런 차이는 정말 크게 느껴집니다.
함수의 기본 모양
파이썬에서 함수를 만들 때는 def를 사용합니다. 함수 이름 뒤에는 괄호 ()를 붙이고, 마지막에는 콜론 :을 씁니다. 그리고 함수 안의 코드는 들여쓰기로 구분합니다.2
가장 단순한 함수부터 보겠습니다.
def greet():
print('안녕하세요!')이 코드는 함수를 정의만 했을 뿐, 아직 실행하지는 않았습니다. 함수를 실제로 사용하려면 호출해야 합니다.
def greet():
print('안녕하세요!')
greet()실행 결과:
안녕하세요!여기서 꼭 기억할 점이 있습니다.
함수를 만든다고 바로 실행되는 것은 아닙니다. 정의와 호출은 다른 일입니다.2
이 차이를 이해하면 함수가 훨씬 덜 헷갈립니다.
매개변수와 인자: 함수에 재료 넣기
함수는 입력을 받을 수 있습니다. 이 입력 덕분에 하나의 함수를 여러 상황에서 유연하게 쓸 수 있습니다.
def greet(name):
print(f'{name}님, 반갑습니다!')
greet('지민')
greet('서윤')실행 결과:
지민님, 반갑습니다!
서윤님, 반갑습니다!여기서 name은 매개변수(parameter) 입니다. 함수를 만들 때 괄호 안에 적는 이름이지요. 그리고 '지민', '서윤'처럼 실제로 넣어 주는 값은 인자(argument) 입니다.3
쉽게 말하면 이렇습니다.
매개변수: 함수가 받을 값의 자리
인자: 그 자리에 실제로 들어가는 값
이 구분은 처음에는 비슷해 보여도, 함수를 이해할수록 아주 중요해집니다.
매개변수가 여러 개인 함수
함수는 값을 여러 개 받을 수도 있습니다.
def add(a, b):
print(a + b)
add(3, 5)실행 결과:
8a와 b는 매개변수입니다. 함수가 호출될 때 3과 5가 각각 들어갑니다.
위치로 넣기와 이름으로 넣기
보통은 순서대로 값을 넣습니다.
def introduce(name, age):
print(f'{name}의 나이는 {age}살입니다.')
introduce('민준', 14)그런데 순서를 바꾸고 싶다면 매개변수 이름을 직접 써서 넣을 수도 있습니다.
introduce(age=14, name='민준')이처럼 이름을 붙여 넣는 방식을 키워드 인자라고 합니다. 순서가 헷갈릴 때 특히 유용합니다.2
기본값이 있는 매개변수
어떤 값은 자주 같은 값으로 들어갑니다. 그럴 때는 기본값을 정해 둘 수 있습니다.2
def greet(name, message='안녕하세요'):
print(f'{message}, {name}!')
greet('하린')
greet('도윤', '좋은 아침')실행 결과:
안녕하세요, 하린!
좋은 아침, 도윤!기본값이 있으면 함수를 더 편하게 부를 수 있습니다. 다만 기본값이 없는 매개변수부터 먼저 쓰는 습관을 들이는 것이 좋습니다.
반환값: 함수가 결과를 돌려주는 법
함수는 일을 한 뒤 결과를 다시 밖으로 보내 줄 수 있습니다. 이때 사용하는 것이 return입니다.4
def add(a, b):
return a + b
result = add(3, 5)
print(result)실행 결과:
8return a + b는 '계산 결과를 함수 바깥으로 돌려줘'라는 뜻입니다. 그래서 add(3, 5)는 숫자 8처럼 사용할 수 있습니다.
print(add(10, 20))
number = add(1, 2)이렇게 함수 호출 결과를 바로 출력하거나 변수에 저장할 수 있습니다.
print()와 return은 다르다
초보자가 가장 자주 헷갈리는 부분입니다.
def add_print(a, b):
print(a + b)
def add_return(a, b):
return a + b두 함수는 비슷해 보이지만 완전히 다릅니다.
x = add_print(2, 3)
print(x)실행 결과:
5
None왜 None이 나올까요? add_print()는 화면에 출력만 했지, 값을 돌려주지는 않았기 때문입니다. 파이썬 함수는 return을 따로 쓰지 않으면 기본적으로 None을 반환합니다.4
반면 add_return()은 결과를 돌려줍니다.
y = add_return(2, 3)
print(y)실행 결과:
5정리하면 이렇습니다.
print()는 화면에 보여 줍니다.return은 값을 돌려줍니다.
보여 주는 것과 돌려주는 것은 전혀 다른 일입니다.
return을 만나면 함수는 끝난다
return은 값을 돌려주는 동시에 함수 실행을 끝냅니다.4
def check_number(n):
if n < 0:
return '음수입니다.'
return '0 또는 양수입니다.'이 함수는 조건에 따라 바로 결과를 돌려주고 끝납니다. 이런 방식을 빠른 반환이라고 생각하면 이해하기 쉽습니다. 복잡한 중첩을 줄여 주기 때문에 코드를 읽기 편하게 만들어 줍니다.
여러 값을 한 번에 돌려주기
파이썬 함수는 값을 여러 개 돌려주는 것처럼 보이게 만들 수도 있습니다. 실제로는 묶어서 반환하는 방식입니다.4
def divide(a, b):
quotient = a // b
remainder = a % b
return quotient, remainder
q, r = divide(17, 3)
print(q)
print(r)실행 결과:
5
2이 기능은 꽤 편리합니다. 관련 있는 결과를 한 번에 보내고 싶을 때 자주 쓰입니다.
함수 안의 변수와 함수 밖의 변수
함수 안에서 만든 변수는 보통 함수 안에서만 사용할 수 있습니다. 이것을 지역 변수라고 합니다.5
def greet():
message = '안녕하세요'
print(message)
greet()
print(message)이 코드를 실행하면 마지막 줄에서 오류가 납니다. message는 함수 안에서만 살아 있기 때문입니다.5
반대로 함수 밖에서 만든 변수는 함수 안에서 읽을 수 있는 경우가 있습니다. 하지만 초보자 단계에서는 함수가 바깥 변수를 마구 건드리게 만들기보다, 필요한 값은 매개변수로 받고 결과는 return으로 돌려주는 방식에 익숙해지는 편이 훨씬 좋습니다.
함수를 깔끔하게 쓰는 가장 쉬운 원칙은 이겁니다.
'밖의 것을 몰래 건드리지 말고, 필요한 것은 입력으로 받고, 결과는 반환하자.'
이 원칙을 지키면 함수가 예측 가능해지고 디버깅도 쉬워집니다.
좋은 함수는 어떤 함수일까
좋은 함수는 거창하지 않습니다. 오히려 작고 분명합니다.
첫째, 한 가지 일을 잘하는 함수가 좋습니다. 예를 들어 평균 계산, 등급 판정, 결과 출력이 모두 한 함수에 섞여 있으면 나중에 수정하기 어렵습니다.
둘째, 이름만 보고도 역할이 드러나야 합니다. do_it()보다는 calculate_average()가 훨씬 친절합니다.
셋째, 입력과 출력이 분명해야 합니다. 무엇을 받아서 무엇을 돌려주는지 알 수 있어야 합니다.
다음 예제를 보겠습니다.
def calculate_average(scores):
return sum(scores) / len(scores)
def get_grade(average):
if average >= 90:
return 'A'
if average >= 80:
return 'B'
if average >= 70:
return 'C'
return 'D'
def print_report(name, scores):
average = calculate_average(scores)
grade = get_grade(average)
print(f'{name}의 평균: {average:.1f}')
print(f'{name}의 등급: {grade}')
print_report('유나', [88, 92, 79])
print_report('시우', [70, 68, 74])이 코드는 함수가 함수를 부르는 구조입니다.
print_report()는 모든 일을 혼자 하지 않습니다. 평균 계산은 calculate_average()에게 맡기고, 등급 판정은 get_grade()에게 맡깁니다. 이런 식으로 코드를 나누면 전체 흐름도 잘 보이고, 나중에 특정 부분만 고치기도 쉽습니다.
예를 들어 등급 기준이 바뀌면 get_grade()만 수정하면 됩니다. 바로 이 점이 함수의 힘입니다.
함수를 나눈다는 것은 생각을 나눈다는 뜻
처음에는 함수를 만드는 일이 단순히 문법처럼 느껴질 수 있습니다. 하지만 실제로는 문법보다 사고방식에 가깝습니다.
긴 문제를 보면 그대로 덤비기보다 이렇게 나누어 보는 습관이 중요합니다.
입력은 무엇인가?
중간 계산은 무엇인가?
마지막 결과는 무엇인가?
이 중에서 반복되거나 따로 떼어 낼 수 있는 일은 무엇인가?
예를 들어 '문장의 단어 수를 세고, 너무 길면 경고를 보여 주는 프로그램'을 만든다고 해 봅시다. 한 덩어리로 쓰는 대신 함수로 나눌 수 있습니다.
def count_words(text):
words = text.split()
return len(words)
def is_long_text(text, limit=10):
return count_words(text) > limit
def print_text_info(text):
word_count = count_words(text)
print(f'단어 수: {word_count}')
if is_long_text(text):
print('문장이 꽤 깁니다.')
else:
print('문장이 길지 않습니다.')
print_text_info('파이썬 함수는 코드를 나누고 다시 쓰기 좋게 만들어 줍니다.')이 프로그램은 아주 크지 않지만, 벌써 구조가 보입니다. count_words()는 단어 수 세기, is_long_text()는 판정, print_text_info()는 출력 담당입니다. 일이 나뉘니 머리도 덜 복잡해집니다.
알아 두면 좋은 함수 사용 습관
함수를 쓸 때는 몇 가지 습관이 큰 차이를 만듭니다.
함수 이름은 가능하면 동사 느낌으로 지으면 좋습니다. print_report, get_grade, count_words처럼 '무엇을 하는지' 드러나기 때문입니다.
또, 계산 함수는 가능하면 print()보다 return을 더 많이 쓰는 편이 좋습니다. 출력은 나중에도 할 수 있지만, 반환값은 다른 계산에 다시 활용할 수 있기 때문입니다.
예를 들어 이런 함수는 활용 범위가 좁습니다.
def square(number):
print(number * number)반면 이렇게 쓰면 더 유용합니다.
def square(number):
return number * number그러면
result = square(5)
print(result)
print(square(3) + square(4))처럼 여러 방식으로 활용할 수 있습니다.
자주 만나는 실수
함수를 처음 배울 때는 비슷한 실수가 반복됩니다. 미리 알고 있으면 덜 헤맵니다.
함수를 정의만 하고 호출하지 않는 실수:
def greet():만 써 놓고greet()를 빼먹으면 아무 일도 일어나지 않습니다.print()와return을 헷갈리는 실수: 화면에 보였다고 해서 그 값이 반환된 것은 아닙니다.매개변수 개수를 틀리는 실수: 두 개를 받는 함수에 하나만 넣거나 세 개를 넣으면 오류가 납니다.
return뒤 코드가 실행될 거라고 생각하는 실수:return을 만나면 함수는 그 자리에서 끝납니다.4함수 안 변수를 밖에서 쓰려는 실수: 함수 안에서 만든 지역 변수는 바깥에서 바로 사용할 수 없습니다.5
이 실수들은 이상한 것이 아닙니다. 누구나 지나가는 길목이라고 생각하면 됩니다.
실전 느낌으로 보는 작은 예제
이번에는 조금 더 '프로그램답게' 만들어 보겠습니다. 사용자의 점수 목록을 받아 평균, 최고점, 최저점을 알려 주는 예제입니다.
def get_average(scores):
return sum(scores) / len(scores)
def get_high_low(scores):
return max(scores), min(scores)
def print_score_summary(name, scores):
average = get_average(scores)
high, low = get_high_low(scores)
print(f'이름: {name}')
print(f'평균: {average:.1f}')
print(f'최고점: {high}')
print(f'최저점: {low}')
print_score_summary('예은', [81, 95, 88, 76])이 예제에서 중요한 점은 결과 자체보다 구조입니다.
print_score_summary()는 필요한 값을 직접 계산하지 않고 다른 함수에게 부탁합니다. 덕분에 각 함수는 짧고 역할이 분명합니다. 이런 구조는 나중에 기능을 더하기 좋습니다. 예를 들어 합격 여부를 추가하고 싶다면 is_passed() 같은 함수를 하나 더 만들면 됩니다.
연습해 보면 더 잘 이해되는 문제들
함수는 읽는 것보다 직접 만들어 보는 쪽이 훨씬 빨리 익습니다. 다음 문제들을 손으로 꼭 풀어 보세요. 초보자 연습용 함수 문제들에서 자주 다루는 패턴을 바탕으로 고른 연습입니다.6
숫자
n을 받아'Hello, Python!'을n번 출력하는 함수를 만들어 보세요.문자열 하나를 받아 대문자 개수, 소문자 개수, 그 외 문자 개수를 세어 딕셔너리로 반환하는 함수를 만들어 보세요.
문자열 리스트를 받아 가장 짧은 단어와 가장 긴 단어를 함께 반환하는 함수를 만들어 보세요.
리스트와 값을 받아, 그 값이 리스트에 없을 때만 추가하는 함수를 만들어 보세요.
숫자 리스트에서 0 이상인 값만 골라 정렬해서 반환하는 함수를 만들어 보세요.
연습할 때는 정답을 빨리 만드는 것보다, 함수 이름을 잘 짓고 입력과 반환값을 분명하게 만드는 것에 더 신경 써 보세요. 그 습관이 실력을 오래 끌고 갑니다.
마무리
함수는 긴 코드를 작고 이해하기 쉬운 조각으로 나누어 줍니다.
함수를 배운다는 것은 단순히 def와 return 문법을 외우는 일이 아닙니다. 프로그램을 '한 번에 다 쓰는 것'에서 '작은 일들로 나누어 조립하는 것'으로 생각을 바꾸는 일입니다.
이제 함수를 볼 때 이렇게 떠올리면 됩니다.
def로 기능에 이름을 붙인다.매개변수로 필요한 값을 받는다.
함수 안에서 한 가지 일을 한다.
return으로 결과를 돌려준다.필요할 때 여러 번 다시 사용한다.
코드를 잘 쓰는 사람은 처음부터 길게 쓰지 않습니다. 작게 나누고, 이름을 붙이고, 다시 조립합니다. 파이썬에서 그 일을 가장 먼저 도와주는 도구가 바로 함수입니다.
참고
1Built-in Functions — Python 3.14.3 documentation
2Python Functions (With Examples)
3Python Function Parameters and Arguments - GeeksforGeeks
4The Python return Statement: Usage and Best Practices
이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.