⚙️
중급 (Intermediate)
*args/**kwargs · lambda · 고차함수 · 클로저
1주차 — 함수 심화
가변 인자(*args, **kwargs), 한 줄 람다, map/filter/sorted with key 같은 고차함수, 그리고 함수 안의 함수가 외부 변수를 기억하는 클로저까지 함수의 표현력을 한 단계 끌어올립니다.
*argslambdahigher-orderclosure
소요 시간
⏱ 2시간
난이도
📊 중급
선수 조건
🎯 기초 9주차
결과물
표현력 있는 함수형 코드 작성
이 강의에서 배우는 것
- 1*args, **kwargs 로 가변 인자를 받는다
- 2람다(lambda) 함수를 사용한다
- 3고차함수 (map, filter, sorted with key) 를 활용한다
- 4클로저(closure)의 동작을 이해한다
1. *args, **kwargs
가변 개수의 인자를 받습니다.
python
def add_all(*args): # args는 튜플
return sum(args)
print(add_all(1, 2, 3)) # 6
print(add_all(1, 2, 3, 4, 5)) # 15
def info(**kwargs): # kwargs는 딕셔너리
for k, v in kwargs.items():
print(f"{k}: {v}")
info(name="홍길동", age=20)조합도 가능: def f(a, b, *args, **kwargs):
2. 람다 함수
이름 없는 한 줄 함수. 즉석 사용에 적합.
python
square = lambda x: x * x
print(square(5)) # 25
# 보통 다른 함수의 인자로 전달
nums = [1, 2, 3, 4, 5]
print(list(map(lambda x: x * 2, nums))) # [2, 4, 6, 8, 10]3. 고차함수
함수를 인자로 받는 함수.
python
nums = [1, 2, 3, 4, 5]
# map: 변환
print(list(map(lambda x: x * x, nums))) # [1, 4, 9, 16, 25]
# filter: 필터링
print(list(filter(lambda x: x % 2, nums))) # [1, 3, 5]
# sorted with key
people = [("Alice", 30), ("Bob", 25), ("Charlie", 28)]
people.sort(key=lambda p: p[1])
print(people)4. 클로저
함수 안에서 정의된 함수가 바깥 변수를 기억.
python
def make_counter():
count = 0
def inc():
nonlocal count # 바깥 변수 수정 시 nonlocal 필요
count += 1
return count
return inc
c = make_counter()
print(c(), c(), c()) # 1 2 35. 자주 하는 실수
- *args 의 위치 — 일반 매개변수 뒤, **kwargs 앞
- 람다에 너무 많은 로직 — 길어지면 그냥 def. 람다는 한 줄
- sorted 와 sort 혼동 — sorted() 는 새 리스트, list.sort() 는 제자리
- 클로저에서 nonlocal 누락 — count += 1 만 쓰면 UnboundLocalError
6. FAQ
Q1. 언제 *args 를 써야 하나요?
인자 개수가 정해지지 않을 때. 예: print, max(1, 2, 3, ...).
Q2. 람다와 일반 함수의 성능 차이?
거의 없음. 람다는 가독성·간결함을 위한 문법 설탕.
Q3. 클로저는 어디에 쓰나요?
데코레이터, 콜백, 상태가 있는 함수. 객체 대신 가벼운 대안.
💻 예제 (examples)
실제로 실행해 결과를 확인할 수 있는 예제 코드입니다.
01_args_kwargs.py— 가변 인자
CODE
def add_all(*args):
return sum(args)
def info(**kwargs):
for k, v in kwargs.items():
print(f"{k}: {v}")
print(add_all(1, 2, 3))
print(add_all(1, 2, 3, 4, 5))
info(name="홍길동", age=20, city="서울")
▶ 실행 결과
6
15
name: 홍길동
age: 20
city: 서울02_lambda.py— 람다 함수
CODE
square = lambda x: x * x
add = lambda a, b: a + b
print(square(5))
print(add(3, 4))
nums = [1, 2, 3, 4, 5]
doubled = list(map(lambda x: x * 2, nums))
print(doubled)
▶ 실행 결과
25
7
[2, 4, 6, 8, 10]03_higher_order.py— map / filter / sorted
CODE
nums = [1, 2, 3, 4, 5]
print(list(map(lambda x: x * x, nums)))
print(list(filter(lambda x: x % 2, nums)))
people = [("Alice", 30), ("Bob", 25), ("Charlie", 28)]
people.sort(key=lambda p: p[1])
print(people)
▶ 실행 결과
[1, 4, 9, 16, 25]
[1, 3, 5]
[('Bob', 25), ('Charlie', 28), ('Alice', 30)]04_closure.py— 클로저와 nonlocal
CODE
def make_counter():
count = 0
def inc():
nonlocal count
count += 1
return count
return inc
c1 = make_counter()
c2 = make_counter() # 독립적 클로저
print(c1(), c1(), c1()) # 1 2 3
print(c2()) # 1 (c1과 독립)
▶ 실행 결과
1 2 3
1📝 과제 (exercises)
직접 풀어보고, 막힐 때 정답을 펼쳐 비교해보세요.
과제 1
stats(*nums) — 평균/분산
목표: 가변 인자로 받은 숫자들의 평균과 분산을 출력한다.
요구사항
- *nums 로 받기
- 평균과 분산을 한 줄에 출력 (분산은 표본분산 또는 모분산)
입출력 예시
평균: 3.0, 분산: 2.0▶정답 코드 펼치기 / 접기
SOLUTION
def stats(*nums):
n = len(nums)
if n == 0:
print("(빈 입력)")
return
mean = sum(nums) / n
var = sum((x - mean) ** 2 for x in nums) / n
print(f"평균: {mean}, 분산: {var}")
stats(1, 2, 3, 4, 5)
▶ 실행 결과
평균: 3.0, 분산: 2.0과제 2
학생 점수 정렬 (sorted with key)
목표: 학생 리스트를 점수 내림차순 + 이름 오름차순으로 정렬한다.
요구사항
- 데이터: [("Alice", 92), ("Bob", 88), ("Charlie", 92), ...]
- 1차: 점수 내림차순, 2차: 이름 오름차순
입출력 예시
[('Alice', 92), ('Charlie', 92), ('Bob', 88)]▶정답 코드 펼치기 / 접기
SOLUTION
students = [("Alice", 92), ("Bob", 88), ("Charlie", 92)]
students.sort(key=lambda s: (-s[1], s[0]))
print(students)
▶ 실행 결과
[('Alice', 92), ('Charlie', 92), ('Bob', 88)]과제 3
make_counter 호출 카운터
목표: make_counter() 로 만든 카운터 함수를 두 개 호출해 독립성을 보인다.
요구사항
- make_counter() 가 inc 함수를 반환
- 각 카운터는 자신만의 count 를 유지
입출력 예시
c1: 1
c1: 2
c2: 1
c1: 3▶정답 코드 펼치기 / 접기
SOLUTION
def make_counter():
count = 0
def inc():
nonlocal count
count += 1
return count
return inc
c1 = make_counter()
c2 = make_counter()
print(f"c1: {c1()}")
print(f"c1: {c1()}")
print(f"c2: {c2()}")
print(f"c1: {c1()}")
▶ 실행 결과
c1: 1
c1: 2
c2: 1
c1: 3