image: path: /assets/img/posts/python/python-mastery-04-functions-lambda.png alt: Python 함수와 람다
🎮 5분만에 배우는 함수의 마법
💸 실전 예제: 할인 계산기 만들기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
| def calculate_discount():
"""쇼핑몰 할인 계산 프로그램"""
# 상품 가격
items = [
{"name": "노트북", "price": 1200000, "qty": 1},
{"name": "마우스", "price": 35000, "qty": 2},
{"name": "키보드", "price": 89000, "qty": 1}
]
def get_total(items):
"""총액 계산 함수"""
return sum(item["price"] * item["qty"] for item in items)
def apply_discount(amount, rate):
"""할인 적용 함수"""
return amount * (1 - rate)
def get_membership_discount(level):
"""회원 등급별 할인율"""
discounts = {
"VIP": 0.20, # 20% 할인
"Gold": 0.15, # 15% 할인
"Silver": 0.10, # 10% 할인
"Bronze": 0.05 # 5% 할인
}
return discounts.get(level, 0)
# 계산 실행
total = get_total(items)
membership = "Gold"
discount_rate = get_membership_discount(membership)
final_price = apply_discount(total, discount_rate)
saved = total - final_price
# 영수증 출력
print("🛒 온라인 쇼핑몰 영수증")
print("="*40)
for item in items:
subtotal = item["price"] * item["qty"]
print(f"{item['name']}: {item['price']:,}원 x {item['qty']}개 = {subtotal:,}원")
print("="*40)
print(f"총액: {total:,}원")
print(f"회원등급: {membership} ({int(discount_rate*100)}% 할인)")
print(f"할인금액: -{saved:,.0f}원")
print(f"결제금액: {final_price:,.0f}원")
return final_price
# 실행
# calculate_discount()
|
🎯 함수란 무엇인가?
함수는 특정 작업을 수행하는 코드 블록으로, 필요할 때마다 호출하여 재사용할 수 있습니다. 코드의 중복을 줄이고, 프로그램을 모듈화하여 유지보수를 쉽게 만들어줍니다.
[!TIP] 초보자를 위한 팁: 함수는 요리 레시피와 같아요!
- 매개변수(Input): 요리 재료 (계란, 소금)
- 함수 내부(Process): 요리 과정 (볶기, 끓이기)
- 반환값(Output): 완성된 요리 (계란말이)
레시피 하나만 잘 만들어두면, 재료만 바꿔서 언제든 맛있는 요리를 만들 수 있죠? 함수도 똑같습니다!
graph LR
A[입력<br/>Input] --> B[함수<br/>Function]
B --> C[처리<br/>Process]
C --> D[출력<br/>Output]
E[매개변수<br/>Parameters] --> B
B --> F[반환값<br/>Return Value]
📝 함수의 기본 구조
함수 정의와 호출
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| # 기본 함수 정의
def greet():
"""인사하는 함수""" # 독스트링 (함수 설명)
print("안녕하세요!")
# 함수 호출
greet() # 안녕하세요!
# 매개변수가 있는 함수
def greet_with_name(name):
"""이름을 받아 인사하는 함수"""
print(f"안녕하세요, {name}님!")
greet_with_name("김파이썬") # 안녕하세요, 김파이썬님!
# 반환값이 있는 함수
def add(a, b):
"""두 수를 더하는 함수"""
return a + b
result = add(3, 5)
print(result) # 8
|
매개변수와 인자
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| # 위치 인자 (Positional Arguments)
def introduce(name, age, city):
print(f"{city}에 사는 {age}살 {name}입니다.")
introduce("홍길동", 25, "서울") # 순서 중요!
# 키워드 인자 (Keyword Arguments)
introduce(city="부산", name="김철수", age=30) # 순서 무관
# 기본값 매개변수 (Default Parameters)
def greet(name, greeting="안녕하세요"):
print(f"{greeting}, {name}님!")
greet("박영희") # 안녕하세요, 박영희님!
greet("이민수", "반갑습니다") # 반갑습니다, 이민수님!
# 주의: 기본값 매개변수는 일반 매개변수 뒤에 위치
# def wrong(greeting="안녕", name): # SyntaxError!
# pass
|
가변 인자 (*args, **kwargs)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| # *args: 가변 위치 인자 (튜플로 수집)
def sum_all(*numbers):
"""여러 개의 숫자를 모두 더하는 함수"""
total = 0
for num in numbers:
total += num
return total
print(sum_all(1, 2, 3)) # 6
print(sum_all(1, 2, 3, 4, 5)) # 15
# **kwargs: 가변 키워드 인자 (딕셔너리로 수집)
def print_info(**info):
"""키워드 인자를 출력하는 함수"""
for key, value in info.items():
print(f"{key}: {value}")
print_info(name="김파이썬", age=25, city="서울")
# *args와 **kwargs 함께 사용
def flexible_function(required, *args, **kwargs):
print(f"필수 인자: {required}")
print(f"추가 위치 인자: {args}")
print(f"키워드 인자: {kwargs}")
flexible_function("필수", 1, 2, 3, name="테스트", debug=True)
|
언패킹 (Unpacking)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # 리스트/튜플 언패킹 (*)
numbers = [1, 2, 3, 4, 5]
print(sum_all(*numbers)) # 리스트를 개별 인자로 전달
# 딕셔너리 언패킹 (**)
info = {"name": "박코딩", "age": 28, "city": "대전"}
print_info(**info) # 딕셔너리를 키워드 인자로 전달
# 함수 정의와 호출에서 모두 사용 가능
def coordinate(x, y, z):
return f"좌표: ({x}, {y}, {z})"
point = (10, 20, 30)
print(coordinate(*point)) # 좌표: (10, 20, 30)
|
🔄 함수의 반환값
단일 반환값과 다중 반환값
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| # 단일 반환값
def square(n):
return n ** 2
# 다중 반환값 (튜플로 반환)
def min_max(numbers):
return min(numbers), max(numbers)
minimum, maximum = min_max([3, 1, 4, 1, 5, 9])
print(f"최소: {minimum}, 최대: {maximum}") # 최소: 1, 최대: 9
# 조건부 반환
def divide(a, b):
if b == 0:
return None # 또는 raise ValueError("0으로 나눌 수 없습니다")
return a / b
# return 없으면 None 반환
def no_return():
print("반환값이 없는 함수")
result = no_return()
print(result) # None
|
[!WARNING] print()와 return의 차이
초보자들이 가장 많이 헷갈리는 부분입니다!
print(): 화면에 보여주기만 하고, 값은 사라집니다. (눈으로 확인용) return: 값을 함수 밖으로 던져줍니다. 다른 변수에 저장하거나 계산에 쓸 수 있습니다. (재사용용)
함수가 값을 “뱉어내게” 하려면 반드시 return을 써야 합니다!
🌟 람다 함수 (Lambda Functions)
📊 실무 예제: 데이터 분석 with Lambda
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
| def employee_data_analysis():
"""람다를 활용한 직원 데이터 분석"""
employees = [
{"name": "김철수", "dept": "개발팀", "salary": 4500, "years": 3},
{"name": "이영희", "dept": "마케팅", "salary": 3800, "years": 2},
{"name": "박민수", "dept": "개발팀", "salary": 5200, "years": 5},
{"name": "정수진", "dept": "인사팀", "salary": 3500, "years": 1},
{"name": "최동욱", "dept": "개발팀", "salary": 6000, "years": 7},
{"name": "강미나", "dept": "마케팅", "salary": 4200, "years": 4}
]
print("🏢 직원 데이터 분석 시스템\n")
# 1. 연봉 5000만원 이상 직원 찾기
high_salary = list(filter(lambda e: e["salary"] >= 5000, employees))
print("💰 고연봉자 (5000만원 이상):")
for emp in high_salary:
print(f" - {emp['name']}: {emp['salary']}만원")
# 2. 부서별 평균 연봉 계산
depts = set(e["dept"] for e in employees)
print("\n📊 부서별 평균 연봉:")
for dept in depts:
dept_employees = list(filter(lambda e: e["dept"] == dept, employees))
avg_salary = sum(e["salary"] for e in dept_employees) / len(dept_employees)
print(f" - {dept}: {avg_salary:,.0f}만원")
# 3. 연차별 정렬 (내림차순)
sorted_by_years = sorted(employees, key=lambda e: e["years"], reverse=True)
print("\n👔 경력 순위:")
for i, emp in enumerate(sorted_by_years[:3], 1):
print(f" {i}위: {emp['name']} ({emp['years']}년차)")
# 4. 연봉 인상 시뮬레이션 (연차 * 2%)
with_raise = list(map(
lambda e: {**e, "new_salary": e["salary"] * (1 + e["years"] * 0.02)},
employees
))
print("\n📈 연봉 인상 시뮬레이션 (연차당 2%):")
for emp in with_raise:
increase = emp["new_salary"] - emp["salary"]
print(f" - {emp['name']}: {emp['salary']}만원 → {emp['new_salary']:.0f}만원 (+{increase:.0f}만원)")
# 5. 개발팀 총 인건비
dev_team_cost = sum(
map(lambda e: e["salary"],
filter(lambda e: e["dept"] == "개발팀", employees))
)
print(f"\n💻 개발팀 총 인건비: {dev_team_cost:,}만원/년")
# 실행
# employee_data_analysis()
|
람다 함수는 이름 없는 익명 함수로, 간단한 함수를 한 줄로 작성할 때 사용합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| # 기본 람다 함수
square = lambda x: x ** 2
print(square(5)) # 25
# 일반 함수와 비교
def square_func(x):
return x ** 2
# 여러 매개변수
add = lambda x, y: x + y
print(add(3, 5)) # 8
# 조건 표현식 포함
max_value = lambda x, y: x if x > y else y
print(max_value(10, 20)) # 20
# 람다 함수의 주요 용도: 고차 함수의 인자
numbers = [1, 2, 3, 4, 5]
# map() 함수와 함께
squared = list(map(lambda x: x ** 2, numbers))
print(squared) # [1, 4, 9, 16, 25]
# filter() 함수와 함께
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens) # [2, 4]
# sorted() 함수와 함께
students = [
{"name": "김철수", "score": 85},
{"name": "이영희", "score": 92},
{"name": "박민수", "score": 78}
]
# 점수로 정렬
sorted_students = sorted(students, key=lambda s: s["score"], reverse=True)
for student in sorted_students:
print(f"{student['name']}: {student['score']}점")
|
🎨 고급 함수 개념
중첩 함수 (Nested Functions)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| def outer_function(x):
"""외부 함수"""
def inner_function(y):
"""내부 함수 - 외부 함수의 변수에 접근 가능"""
return x + y
return inner_function
# 클로저 생성
add_five = outer_function(5)
print(add_five(3)) # 8
print(add_five(10)) # 15
# 실용적 예제: 설정 가능한 할인율 계산기
def discount_calculator(discount_rate):
"""할인율을 설정하는 계산기 생성"""
def calculate_price(original_price):
return original_price * (1 - discount_rate)
return calculate_price
# 10% 할인 계산기
ten_percent_off = discount_calculator(0.1)
print(ten_percent_off(10000)) # 9000.0
# 30% 할인 계산기
thirty_percent_off = discount_calculator(0.3)
print(thirty_percent_off(10000)) # 7000.0
|
고차 함수 (Higher-Order Functions)
함수를 인자로 받거나 함수를 반환하는 함수입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
| # 함수를 인자로 받는 고차 함수
def apply_operation(func, x, y):
"""주어진 함수를 x와 y에 적용"""
return func(x, y)
def add(a, b):
return a + b
def multiply(a, b):
return a * b
print(apply_operation(add, 5, 3)) # 8
print(apply_operation(multiply, 5, 3)) # 15
# 함수를 반환하는 고차 함수
def make_multiplier(n):
"""n배 하는 함수를 반환"""
def multiplier(x):
return x * n
return multiplier
double = make_multiplier(2)
triple = make_multiplier(3)
print(double(5)) # 10
print(triple(5)) # 15
# 내장 고차 함수들
from functools import reduce
numbers = [1, 2, 3, 4, 5]
# map: 각 요소에 함수 적용
doubled = list(map(lambda x: x * 2, numbers))
print(doubled) # [2, 4, 6, 8, 10]
# filter: 조건을 만족하는 요소만 선택
odds = list(filter(lambda x: x % 2 == 1, numbers))
print(odds) # [1, 3, 5]
# reduce: 누적 연산
total = reduce(lambda x, y: x + y, numbers)
print(total) # 15
|
데코레이터 기초
데코레이터는 함수를 수정하지 않고 기능을 추가하는 방법입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
| # 간단한 데코레이터
def timer_decorator(func):
"""함수 실행 시간을 측정하는 데코레이터"""
import time
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} 실행 시간: {end - start:.4f}초")
return result
return wrapper
# 데코레이터 사용
@timer_decorator
def slow_function():
"""시간이 걸리는 함수"""
import time
time.sleep(1)
return "완료!"
result = slow_function() # slow_function 실행 시간: 1.0XXX초
print(result) # 완료!
# 로깅 데코레이터
def log_decorator(func):
"""함수 호출을 로깅하는 데코레이터"""
def wrapper(*args, **kwargs):
print(f"호출: {func.__name__}({args}, {kwargs})")
result = func(*args, **kwargs)
print(f"반환: {result}")
return result
return wrapper
@log_decorator
def add(a, b):
return a + b
add(3, 5)
# 호출: add((3, 5), {})
# 반환: 8
|
💡 실전 예제
1. 계산기 프로그램 (함수 활용)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
| def calculator_program():
"""함수를 활용한 계산기 프로그램"""
# 기본 연산 함수들
def add(x, y):
return x + y
def subtract(x, y):
return x - y
def multiply(x, y):
return x * y
def divide(x, y):
if y == 0:
raise ValueError("0으로 나눌 수 없습니다")
return x / y
def power(x, y):
return x ** y
# 연산 딕셔너리
operations = {
'+': add,
'-': subtract,
'*': multiply,
'/': divide,
'**': power
}
# 계산 기록
history = []
def calculate(x, operator, y):
"""계산 수행 및 기록"""
if operator not in operations:
raise ValueError(f"지원하지 않는 연산자: {operator}")
result = operations[operator](x, y)
history.append(f"{x} {operator} {y} = {result}")
return result
def show_history():
"""계산 기록 표시"""
if not history:
print("계산 기록이 없습니다.")
else:
print("\n=== 계산 기록 ===")
for i, record in enumerate(history, 1):
print(f"{i}. {record}")
# 메인 루프
print("=== 함수형 계산기 ===")
print("연산자: +, -, *, /, **")
print("명령: history(기록 보기), quit(종료)")
while True:
user_input = input("\n수식 입력 (예: 5 + 3): ").strip()
if user_input.lower() == 'quit':
break
elif user_input.lower() == 'history':
show_history()
continue
try:
parts = user_input.split()
if len(parts) != 3:
print("올바른 형식: 숫자 연산자 숫자")
continue
x = float(parts[0])
operator = parts[1]
y = float(parts[2])
result = calculate(x, operator, y)
print(f"결과: {result}")
except ValueError as e:
print(f"에러: {e}")
except Exception as e:
print(f"예상치 못한 에러: {e}")
# 실행
# calculator_program()
|
2. 함수형 프로그래밍 스타일 데이터 처리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
| def functional_data_processing():
"""함수형 프로그래밍 스타일로 데이터 처리"""
# 샘플 데이터
employees = [
{"name": "김철수", "department": "개발", "salary": 4500, "years": 3},
{"name": "이영희", "department": "마케팅", "salary": 3800, "years": 2},
{"name": "박민수", "department": "개발", "salary": 5200, "years": 5},
{"name": "최지원", "department": "인사", "salary": 3500, "years": 1},
{"name": "정대현", "department": "개발", "salary": 4800, "years": 4},
]
# 1. 개발 부서 직원만 필터링
developers = list(filter(lambda e: e["department"] == "개발", employees))
print("개발 부서 직원:")
for dev in developers:
print(f" - {dev['name']}")
# 2. 모든 직원의 연봉 10% 인상 계산
def raise_salary(employee):
return {**employee, "salary": employee["salary"] * 1.1}
raised_employees = list(map(raise_salary, employees))
print("\n10% 인상 후 연봉:")
for emp in raised_employees:
print(f" - {emp['name']}: {emp['salary']:.0f}만원")
# 3. 경력 3년 이상 직원의 평균 연봉
senior_employees = filter(lambda e: e["years"] >= 3, employees)
senior_salaries = map(lambda e: e["salary"], senior_employees)
avg_salary = sum(senior_salaries) / len([e for e in employees if e["years"] >= 3])
print(f"\n경력 3년 이상 평균 연봉: {avg_salary:.0f}만원")
# 4. 부서별 직원 수 계산
from collections import defaultdict
def group_by_department(employees):
groups = defaultdict(list)
for emp in employees:
groups[emp["department"]].append(emp)
return dict(groups)
dept_groups = group_by_department(employees)
print("\n부서별 직원 수:")
for dept, emps in dept_groups.items():
print(f" - {dept}: {len(emps)}명")
# 5. 커링(Currying) 패턴으로 급여 필터 생성
def salary_filter(min_salary):
return lambda emp: emp["salary"] >= min_salary
high_earners = filter(salary_filter(4500), employees)
print("\n연봉 4500만원 이상:")
for emp in high_earners:
print(f" - {emp['name']}: {emp['salary']}만원")
# 실행
# functional_data_processing()
|
3. 데코레이터 활용 예제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
| import functools
import time
# 캐싱 데코레이터
def memoize(func):
"""결과를 캐싱하는 데코레이터"""
cache = {}
@functools.wraps(func)
def wrapper(*args):
if args in cache:
print(f"캐시에서 반환: {args}")
return cache[args]
result = func(*args)
cache[args] = result
return result
wrapper.cache = cache # 캐시 접근 가능하도록
return wrapper
# 재시도 데코레이터
def retry(max_attempts=3, delay=1):
"""실패시 재시도하는 데코레이터"""
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(max_attempts):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_attempts - 1:
raise
print(f"시도 {attempt + 1} 실패: {e}")
time.sleep(delay)
return None
return wrapper
return decorator
# 입력 검증 데코레이터
def validate_positive(func):
"""양수만 허용하는 데코레이터"""
@functools.wraps(func)
def wrapper(*args, **kwargs):
for arg in args:
if isinstance(arg, (int, float)) and arg < 0:
raise ValueError(f"음수는 허용되지 않습니다: {arg}")
return func(*args, **kwargs)
return wrapper
# 데코레이터 사용 예제
@memoize
def fibonacci(n):
"""피보나치 수열 (캐싱 적용)"""
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
@retry(max_attempts=3, delay=0.5)
def unstable_network_call():
"""불안정한 네트워크 호출 시뮬레이션"""
import random
if random.random() < 0.7: # 70% 확률로 실패
raise ConnectionError("네트워크 연결 실패")
return "성공!"
@validate_positive
def calculate_area(width, height):
"""사각형 넓이 계산 (양수 검증)"""
return width * height
# 테스트
print("=== 피보나치 (캐싱) ===")
print(f"fibonacci(10) = {fibonacci(10)}")
print(f"fibonacci(10) = {fibonacci(10)}") # 캐시에서 반환
print("\n=== 불안정한 네트워크 호출 ===")
try:
result = unstable_network_call()
print(f"결과: {result}")
except ConnectionError as e:
print(f"최종 실패: {e}")
print("\n=== 넓이 계산 (검증) ===")
try:
print(f"넓이: {calculate_area(5, 3)}")
print(f"넓이: {calculate_area(-5, 3)}") # ValueError
except ValueError as e:
print(f"에러: {e}")
|
⚠️ 초보자가 자주 하는 실수
1. 기본값 매개변수 실수
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # ❌ 가변 객체를 기본값으로 사용
def add_item(item, items=[]): # 위험!
items.append(item)
return items
print(add_item("apple")) # ['apple']
print(add_item("banana")) # ['apple', 'banana'] - 예상과 다름!
# ✅ None을 기본값으로 사용
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
|
[!CAUTION] 기본값으로 리스트를 쓰지 마세요!
리스트 같은 가변 객체(Mutable Object)를 기본값으로 쓰면, 함수가 실행될 때마다 리스트가 초기화되는 게 아니라 계속 재사용됩니다. 그래서 앞서 추가한 아이템이 계속 남아있게 됩니다. 반드시 None을 사용하세요!
2. 변수 스코프 실수
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| # ❌ 전역 변수와 지역 변수 혼동
count = 10
def increment():
count = count + 1 # UnboundLocalError!
return count
# ✅ global 키워드 사용 또는 매개변수로 전달
def increment():
global count
count = count + 1
return count
# 더 좋은 방법 - 매개변수와 반환값 사용
def increment(count):
return count + 1
|
3. return 실수
1
2
3
4
5
6
7
8
9
10
11
12
13
| # ❌ return 위치 실수
def find_first_even(numbers):
for num in numbers:
if num % 2 == 0:
print(f"Found: {num}")
return num # 첫 번째 숫자만 반환!
# ✅ 올바른 위치
def find_first_even(numbers):
for num in numbers:
if num % 2 == 0:
return num
return None
|
4. 람다 함수 실수
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # ❌ 복잡한 로직을 람다로 작성
result = lambda x: print(x) if x > 0 else (print("negative") if x < 0 else print("zero"))
# ✅ 복잡한 로직은 일반 함수로
def check_number(x):
if x > 0:
return "positive"
elif x < 0:
return "negative"
else:
return "zero"
# ❌ 람다 함수에서 반복문
# lambda x: for i in x: print(i) # SyntaxError!
# ✅ 리스트 컴프리헨션 사용
lambda x: [print(i) for i in x]
|
5. 인자 전달 실수
1
2
3
4
5
6
7
8
9
| # ❌ *args를 잘못 전달
def sum_numbers(*args):
return sum(args)
numbers = [1, 2, 3, 4, 5]
# print(sum_numbers(numbers)) # TypeError!
# ✅ 언패킹 사용
print(sum_numbers(*numbers)) # 15
|
🎯 핵심 정리
함수 설계 Best Practices
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
| # 1. 단일 책임 원칙
# 좋음: 한 가지 일만 하는 함수
def calculate_total(prices):
return sum(prices)
def apply_discount(total, discount_rate):
return total * (1 - discount_rate)
# 나쁨: 여러 일을 하는 함수
def calculate_and_print_with_discount(prices, discount_rate):
total = sum(prices)
discounted = total * (1 - discount_rate)
print(f"Total: {total}, After discount: {discounted}")
return discounted
# 2. 명확한 함수명과 매개변수명
def get_user_by_id(user_id): # 좋음
pass
def get(id): # 나쁨 - 무엇을 가져오는지 불명확
pass
# 3. 타입 힌트 사용 (Python 3.5+)
def greet(name: str, age: int) -> str:
return f"{name}님은 {age}살입니다."
# 4. 독스트링 작성
def calculate_bmi(weight: float, height: float) -> float:
"""
BMI(체질량지수)를 계산합니다.
Args:
weight: 체중 (kg)
height: 키 (m)
Returns:
BMI 값
Raises:
ValueError: 체중이나 키가 0 이하인 경우
"""
if weight <= 0 or height <= 0:
raise ValueError("체중과 키는 양수여야 합니다")
return weight / (height ** 2)
|
람다 함수 사용 가이드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| # 람다가 적합한 경우
# 1. 간단한 변환
numbers = [1, 2, 3, 4, 5]
squared = map(lambda x: x**2, numbers)
# 2. 정렬 키
students.sort(key=lambda s: s['score'])
# 3. 필터링
adults = filter(lambda p: p['age'] >= 18, people)
# 람다가 부적합한 경우
# 1. 복잡한 로직 - 일반 함수 사용
def complex_calculation(x, y, z):
if x > 0:
return (x + y) * z
else:
return (x - y) / z
# 2. 재사용이 필요한 경우
def is_even(n):
return n % 2 == 0
even_nums = filter(is_even, numbers) # 여러 곳에서 재사용 가능
|
🎓 파이썬 마스터하기 시리즈
📚 기초편 (1-7)
- Python 소개와 개발 환경 설정 완벽 가이드
- 변수, 자료형, 연산자 완벽 정리
- 조건문과 반복문 마스터하기
- 함수와 람다 완벽 가이드
- 리스트, 튜플, 딕셔너리 정복하기
- 문자열 처리와 정규표현식
- 파일 입출력과 예외 처리
🚀 중급편 (8-12)
- 클래스와 객체지향 프로그래밍
- 모듈과 패키지 관리
- 데코레이터와 제너레이터
- 비동기 프로그래밍 (async/await)
- 데이터베이스 연동하기
💼 고급편 (13-16)
- 웹 스크래핑과 API 활용
- 테스트와 디버깅 전략
- 성능 최적화 기법
- 멀티프로세싱과 병렬 처리
이전글: 조건문과 반복문 마스터하기 ⬅️ 현재글: 함수와 람다 완벽 가이드 다음글: 리스트, 튜플, 딕셔너리 정복하기 ➡️
이번 포스트에서는 코드 재사용의 핵심인 함수와 람다에 대해 알아보았습니다. 다음 포스트에서는 Python의 핵심 자료구조인 리스트, 튜플, 딕셔너리를 완벽히 정복해보겠습니다. Happy Coding! 🐍✨