파이썬 함수(def) 완벽 정리: 매개변수, return, *args, 전역변수 한 번에
파이썬 함수 사용법을 한 곳에 모았습니다. def 기본 정의, return과 print의 차이, 여러 값 반환, *args·**kwargs 가변 인자, 전역/지역변수, 람다·재귀 함수까지. 모든 예제는 복사해서 바로 실행할 수 있습니다.
파이썬으로 코드가 길어지기 시작하면 반드시 마주치는 게 함수입니다. "파이썬 함수 정의", "return과 print 차이", "가변 인자 args kwargs", "전역변수 사용법"… 매번 비슷한 걸 찾게 되죠.
이 글은 파이썬 함수의 핵심을 한 곳에 모았습니다. 기본 정의부터 매개변수, 반환값, 가변 인자, 전역/지역변수까지 전부 복사해서 바로 쓸 수 있게 정리했습니다. 북마크해두고 필요할 때마다 꺼내 쓰세요.
동작 환경: Python 3.x (타입 힌트는 3.5+, 더 간결한 문법은 3.9+ 권장)
함수 기본 정의 (def)
def greet():
print("안녕하세요")
greet() # 함수 호출 → "안녕하세요" 출력
def 함수이름(매개변수): 형태로 정의하고, 본문은 들여쓰기로 구분합니다.
매개변수와 인자
함수를 정의할 때 괄호 안에 쓰는 게 매개변수(parameter), 호출할 때 실제로 넘기는 값이 **인자(argument)**입니다.
def add(a, b): # a, b는 매개변수
return a + b
add(3, 5) # 3, 5는 인자 → 8
기본값 매개변수 — 인자를 안 넘기면 기본값이 사용됩니다.
def greet(name="손님"):
print(f"안녕하세요, {name}님")
greet() # "안녕하세요, 손님님"
greet("김철수") # "안녕하세요, 김철수님"
기본값이 있는 매개변수는 반드시 없는 매개변수 뒤에 와야 합니다.
def f(a, b=1)은 되지만def f(a=1, b)는 에러입니다.
return과 print의 차이 (매우 자주 헷갈리는 부분)
초보자가 가장 많이 헷갈리는 개념입니다. print는 화면에 보여줄 뿐이고, return은 값을 함수 밖으로 돌려줍니다.
def add_print(a, b):
print(a + b) # 화면에 출력만 함
def add_return(a, b):
return a + b # 값을 반환함
result1 = add_print(3, 5) # 화면에 8이 출력되지만, result1은 None!
result2 = add_return(3, 5) # 화면엔 아무것도 안 뜨지만, result2는 8
print(result1) # None
print(result2) # 8
함수의 결과를 다른 곳에서 재사용하려면 반드시 return을 써야 합니다. print는 눈으로 확인하는 용도일 뿐, 값을 넘겨주지 않습니다.
return을 만나면 함수는 그 즉시 종료됩니다. 이후 코드는 실행되지 않습니다.
def check(x):
if x > 0:
return "양수"
return "0 이하" # x > 0이 아닐 때만 도달
여러 값 반환하기
파이썬은 return에 값을 콤마로 나열하면 튜플로 묶여 반환됩니다.
def min_max(arr):
return min(arr), max(arr)
lo, hi = min_max([3, 1, 4, 1, 5]) # lo=1, hi=5 (자동 언패킹)
# 반환값을 튜플 그대로 받을 수도 있음
result = min_max([3, 1, 4])
print(result) # (1, 4)
가변 인자: *args, **kwargs
인자의 개수가 정해지지 않았을 때 사용합니다. 검색량이 매우 높은 패턴입니다.
# *args: 여러 개의 위치 인자를 튜플로 받음
def total(*args):
return sum(args)
total(1, 2, 3) # 6
total(1, 2, 3, 4, 5) # 15
# **kwargs: 여러 개의 키워드 인자를 딕셔너리로 받음
def print_info(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
print_info(name="Kim", age=25)
# name: Kim
# age: 25
# 함께 사용
def func(a, b, *args, **kwargs):
print(a, b, args, kwargs)
func(1, 2, 3, 4, x=10, y=20)
# 1 2 (3, 4) {'x': 10, 'y': 20}
*args와 **kwargs라는 이름 자체는 관례일 뿐이고, 중요한 건 *와 ** 기호입니다. 원하는 다른 이름을 써도 동작은 같습니다.
키워드 인자로 호출하기
인자를 이름으로 지정해서 넘기면 순서를 신경 쓰지 않아도 됩니다.
def greet(name, greeting="안녕"):
print(f"{greeting}, {name}")
greet(name="철수", greeting="반가워")
greet(greeting="반가워", name="철수") # 순서 바꿔도 결과 동일
리스트나 딕셔너리를 함수 인자로 풀어서 전달할 때도 *, **를 씁니다.
def add(a, b, c):
return a + b + c
nums = [1, 2, 3]
add(*nums) # 6 — 리스트를 풀어서 각각 전달
info = {"a": 1, "b": 2, "c": 3}
add(**info) # 6 — 딕셔너리를 풀어서 키워드 인자로 전달
전역변수와 지역변수 (global)
함수 안에서 만든 변수는 함수 밖에서 접근할 수 없습니다(지역변수). 함수 밖의 변수를 함수 안에서 수정하려면 global 키워드가 필요합니다.
count = 0 # 전역변수
def increment():
count += 1 # ❌ UnboundLocalError!
# 함수 안에서 count에 값을 대입하는 순간, 파이썬은 count를 지역변수로 간주함
def increment_fixed():
global count # 전역변수 count를 쓰겠다고 선언
count += 1 # ✅ 정상 동작
increment_fixed()
print(count) # 1
다만 실무에서는
global을 남발하면 코드 추적이 어려워집니다. 값을 바꿔야 한다면return으로 새 값을 반환하고 재할당하는 방식을 더 권장합니다.
def increment(count):
return count + 1
count = increment(count) # global 없이도 값 갱신 가능
람다 함수 (익명 함수)
이름 없이 간단한 함수를 한 줄로 만들 때 씁니다. 주로 sorted, map, filter의 key/함수 인자로 쓰입니다.
square = lambda x: x ** 2
square(5) # 25
# 정렬 key로 활용 (가장 흔한 사용처)
data = [(1, "b"), (2, "a")]
sorted(data, key=lambda x: x[1]) # [(2, 'a'), (1, 'b')]
로직이 복잡하면 람다 대신 일반 def 함수로 작성하는 것이 가독성 면에서 낫습니다.
재귀 함수
함수가 자기 자신을 호출하는 방식입니다. 반드시 **종료 조건(base case)**이 있어야 무한 재귀를 피할 수 있습니다.
def factorial(n):
if n <= 1: # 종료 조건 (base case)
return 1
return n * factorial(n - 1) # 자기 자신 호출
factorial(5) # 120
타입 힌트 (선택 사항이지만 실무에서 많이 씀)
함수의 매개변수와 반환값의 타입을 명시할 수 있습니다. 실행에 영향을 주진 않지만 가독성과 IDE 자동완성에 도움이 됩니다.
def add(a: int, b: int) -> int:
return a + b
def greet(name: str = "손님") -> None:
print(f"안녕하세요, {name}")
자주 묻는 질문
Q. return 없이 함수가 끝나면 어떻게 되나요?
None을 반환합니다. return문이 아예 없거나 값 없이 return만 쓴 경우 모두 None이 반환됩니다.
**Q. *args와 kwargs를 꼭 같이 써야 하나요?
아닙니다. 필요한 것만 써도 됩니다. 위치 인자만 가변적이면 *args만, 키워드 인자만 가변적이면 **kwargs만 씁니다.
Q. 함수 안에서 전역변수를 읽기만 할 때도 global이 필요한가요?
아닙니다. 읽기만 할 때는 global 없이도 접근됩니다. global은 함수 안에서 전역변수에 **값을 대입(재할당)**할 때만 필요합니다.
마무리
파이썬 함수의 핵심은 **정의는 def, 값을 돌려주려면 return, 화면 확인용은 print**라는 것입니다. 이 둘을 헷갈리면 함수의 결과를 다른 코드에서 쓸 수 없는 흔한 버그로 이어집니다.
인자 개수가 유동적이면 *args/**kwargs, 전역변수를 함수 안에서 수정해야 하면 global을 쓰되 가능하면 return 기반으로 설계하는 것이 유지보수에 유리합니다. 필요할 때마다 이 글을 다시 펼쳐 해당 섹션을 복사해 쓰세요.
함께 보면 좋은 글: [파이썬 조건문 완벽 정리], [파이썬 반복문 완벽 정리]