Python Programming
  • Home
  • Intro
    • History & Background
    • Python Setup
  • QPB
    • Part I: Chapter 1-3
    • Part II
    • 5. Lists, Tuples, Sets
  • Exercises
    • Chapter 5: Lists, Tuples, Sets
    • Chapter 6: Strings
    • Chapter 7: Dictionaries
    • Chapter 8: Control flow
    • Chapter 9: Functions
    • Chapter 14: Exceptions
    • Chapter 15: Classes
  • Exploring Data
    • NumPy & pandas
    • Visualization
  • Library System
  • Netflix Movie Analysis
    • Notes
    • Project-Native
    • Project-pandas
  • References
    • QPB Part 1
    • QPB Part 2
    • QPB Part 3
    • QPB Part 4

On this page

  • 문제 1: 기본 함수와 Docstring
  • 문제 2: 기본값과 키워드 인자
  • 문제 3: 가변 위치 인자 (*args)
  • 문제 4: 가변 키워드 인자 (**kwargs)
  • 문제 5: Mutable 객체와 부작용
  • 문제 6: Local vs Global 변수
  • 문제 7: 함수를 변수에 할당
  • 문제 8: Lambda 표현식 활용
  • 문제 9: Generator 함수 기초
  • 문제 10: Generator를 사용한 데이터 파이프라인
  • 문제 11**: 다목적 Decorator 만들기

Exercises: Chapter 9

Chapter 9: Functions - 연습문제

함수 정의, 매개변수, 지역/전역 변수, 람다, 제너레이터, 데코레이터

문제 1: 기본 함수와 Docstring

다음 요구사항에 맞는 함수를 작성하세요:

  1. 이름: calculate_bmi
  2. 매개변수: weight (kg), height (m)
  3. 반환값: BMI 수치 (체중 / 신장²)
  4. Docstring 작성 (함수 설명, 매개변수, 반환값 포함)
  5. BMI 범주 판정 추가:
    • 18.5 미만: “저체중”
    • 18.5~23 미만: “정상”
    • 23~25 미만: “과체중”
    • 25 이상: “비만”

함수를 호출하고 __doc__ 속성으로 docstring을 출력하세요.

출력 예시:

BMI: 24.22
범주: 과체중
# 여기에 코드를 작성하세요


문제 2: 기본값과 키워드 인자

온라인 쇼핑몰의 가격 계산 함수를 작성하세요:

def calculate_price(price, quantity=1, discount=0, tax_rate=0.1):
    # 구현

계산 방식:

  1. 기본 금액 = price × quantity
  2. 할인 적용 = 기본 금액 × (1 - discount)
  3. 세금 포함 = 할인 적용 금액 × (1 + tax_rate)

테스트:

calculate_price(10000)  # 11000.0
calculate_price(10000, quantity=3)  # 33000.0
calculate_price(10000, quantity=2, discount=0.2)  # 17600.0
calculate_price(10000, discount=0.1, tax_rate=0)  # 9000.0
# 여기에 코드를 작성하세요


문제 3: 가변 위치 인자 (*args)

여러 개의 숫자를 받아 통계 정보를 반환하는 함수를 작성하세요:

def number_stats(*numbers):
    # 구현

반환값: 딕셔너리

  • count: 숫자 개수
  • sum: 합계
  • mean: 평균
  • min: 최솟값
  • max: 최댓값

주의: 인자가 없을 때는 적절한 메시지와 함께 None 반환

테스트:

number_stats(1, 2, 3, 4, 5)
# {'count': 5, 'sum': 15, 'mean': 3.0, 'min': 1, 'max': 5}

number_stats(10, 20)
# {'count': 2, 'sum': 30, 'mean': 15.0, 'min': 10, 'max': 20}
# 여기에 코드를 작성하세요


문제 4: 가변 키워드 인자 (**kwargs)

학생 정보를 받아 프로필 문자열을 생성하는 함수를 작성하세요:

def create_student_profile(name, student_id, **additional_info):
    # 구현

요구사항:

  1. name과 student_id는 필수
  2. 추가 정보는 키워드 인자로 자유롭게 받기
  3. 모든 정보를 보기 좋게 정리하여 문자열로 반환

테스트:

print(create_student_profile(
    "김철수", 
    "2023001",
    major="컴퓨터공학",
    grade=3,
    gpa=3.8,
    club="코딩동아리"
))

출력 예시:

=== 학생 프로필 ===
이름: 김철수
학번: 2023001
전공: 컴퓨터공학
학년: 3
학점: 3.8
동아리: 코딩동아리
# 여기에 코드를 작성하세요


문제 5: Mutable 객체와 부작용

다음 두 가지 버전의 리스트 처리 함수를 작성하고 차이를 설명하세요:

버전 1: 원본 수정 (in-place)

def remove_negatives_inplace(numbers):
    """원본 리스트에서 음수 제거"""
    # 구현

버전 2: 새 리스트 반환

def remove_negatives_copy(numbers):
    """새 리스트를 만들어 반환 (원본 유지)"""
    # 구현

테스트 코드:

# 버전 1 테스트
list1 = [1, -2, 3, -4, 5, -6]
remove_negatives_inplace(list1)
print("버전 1 - 원본:", list1)  # [1, 3, 5]

# 버전 2 테스트
list2 = [1, -2, 3, -4, 5, -6]
new_list = remove_negatives_copy(list2)
print("버전 2 - 원본:", list2)  # [1, -2, 3, -4, 5, -6]
print("버전 2 - 새 리스트:", new_list)  # [1, 3, 5]

질문: 어떤 상황에서 각 버전을 사용하는 것이 좋을까요?

# 여기에 코드를 작성하세요


문제 6: Local vs Global 변수

다음 코드의 출력을 예측하고, 실제로 실행하여 확인하세요. 그리고 각 경우를 설명하세요.

counter = 0

def test1():
    counter = 10
    print("test1 내부:", counter)

def test2():
    global counter
    counter = 20
    print("test2 내부:", counter)

def test3():
    print("test3 내부:", counter)

print("초기:", counter)
test1()
print("test1 후:", counter)
test2()
print("test2 후:", counter)
test3()

추가 문제: 은행 계좌 클래스를 구현하되, 전체 계좌의 총 잔액을 추적하는 전역 변수를 사용하세요.

# 여기에 코드를 작성하세요


문제 7: 함수를 변수에 할당

여러 변환 함수를 딕셔너리에 저장하고 활용하는 시스템을 만드세요:

요구사항:

  1. 온도 변환 함수들 작성:
    • celsius_to_fahrenheit: 섭씨 → 화씨
    • fahrenheit_to_celsius: 화씨 → 섭씨
    • celsius_to_kelvin: 섭씨 → 켈빈
    • kelvin_to_celsius: 켈빈 → 섭씨
  2. 함수를 딕셔너리에 저장:
converters = {
    'c_to_f': celsius_to_fahrenheit,
    # ...
}
  1. 사용자 입력을 받아 해당 변환 실행

테스트:

convert_temperature(100, 'c_to_f')  # 212.0
convert_temperature(32, 'f_to_c')   # 0.0
convert_temperature(0, 'c_to_k')    # 273.15
# 여기에 코드를 작성하세요


문제 8: Lambda 표현식 활용

다음 데이터를 lambda 표현식을 사용하여 다양하게 정렬하세요:

products = [
    {'name': 'Laptop', 'price': 1200, 'rating': 4.5, 'stock': 15},
    {'name': 'Mouse', 'price': 25, 'rating': 4.8, 'stock': 50},
    {'name': 'Keyboard', 'price': 75, 'rating': 4.3, 'stock': 30},
    {'name': 'Monitor', 'price': 300, 'rating': 4.7, 'stock': 20},
]

작업:

  1. 가격 기준 오름차순 정렬
  2. 평점 기준 내림차순 정렬
  3. 재고가 30 이상인 제품만 필터링 (filter 사용)
  4. 모든 가격을 10% 인상 (map 사용)
  5. 가격/평점 비율로 정렬 (가성비 순)

힌트: sorted(), filter(), map() 함수와 lambda를 조합하세요.

# 여기에 코드를 작성하세요
products = [
    {'name': 'Laptop', 'price': 1200, 'rating': 4.5, 'stock': 15},
    {'name': 'Mouse', 'price': 25, 'rating': 4.8, 'stock': 50},
    {'name': 'Keyboard', 'price': 75, 'rating': 4.3, 'stock': 30},
    {'name': 'Monitor', 'price': 300, 'rating': 4.7, 'stock': 20},
]


문제 9: Generator 함수 기초

다음 generator 함수들을 작성하세요:

1. 피보나치 수열 생성기

def fibonacci(n):
    """처음 n개의 피보나치 수를 생성"""
    # yield 사용하여 구현

2. 파일 줄 단위 읽기

def read_lines(filename):
    """파일을 한 줄씩 읽어 yield"""
    # 빈 줄과 주석(#으로 시작)은 건너뛰기

3. 무한 카운터

def infinite_counter(start=0, step=1):
    """무한히 증가하는 카운터"""
    # 구현

테스트:

# 피보나치
for num in fibonacci(10):
    print(num, end=' ')  # 0 1 1 2 3 5 8 13 21 34

# 무한 카운터 (처음 5개만)
counter = infinite_counter(10, 2)
for _ in range(5):
    print(next(counter))  # 10 12 14 16 18
# 여기에 코드를 작성하세요


문제 10: Generator를 사용한 데이터 파이프라인

대용량 로그 파일을 처리하는 generator 파이프라인을 구현하세요:

# 샘플 로그 데이터
log_lines = [
    "2024-01-01 10:00:00 INFO User login: user123",
    "2024-01-01 10:05:00 ERROR Database connection failed",
    "2024-01-01 10:10:00 INFO User logout: user123",
    "2024-01-01 10:15:00 WARNING High memory usage: 85%",
    "2024-01-01 10:20:00 ERROR File not found: data.txt",
]

구현할 generator 함수들:

  1. generate_logs(lines): 로그 라인을 하나씩 yield
  2. parse_log(logs): 각 로그를 딕셔너리로 파싱
    • {'timestamp': ..., 'level': ..., 'message': ...}
  3. filter_by_level(logs, level): 특정 레벨만 필터링
  4. format_log(logs): 로그를 보기 좋게 포맷

사용 예시:

# Generator 체인
logs = generate_logs(log_lines)
parsed = parse_log(logs)
errors = filter_by_level(parsed, 'ERROR')
formatted = format_log(errors)

for log in formatted:
    print(log)

힌트: Generator는 필요할 때만 데이터를 처리하므로 메모리 효율적입니다.

# 여기에 코드를 작성하세요
log_lines = [
    "2024-01-01 10:00:00 INFO User login: user123",
    "2024-01-01 10:05:00 ERROR Database connection failed",
    "2024-01-01 10:10:00 INFO User logout: user123",
    "2024-01-01 10:15:00 WARNING High memory usage: 85%",
    "2024-01-01 10:20:00 ERROR File not found: data.txt",
]


문제 11**: 다목적 Decorator 만들기

함수의 실행 시간을 측정하고 결과를 캐싱하는 decorator를 작성하세요.

요구사항:

  1. @timer: 함수 실행 시간 측정
  2. @memoize: 함수 결과 캐싱 (같은 인자로 호출 시 저장된 결과 반환)
  3. 두 decorator를 함께 사용 가능해야 함

기본 구조:

import time

def timer(func):
    """함수 실행 시간을 측정하는 decorator"""
    def wrapper(*args, **kwargs):
        start_time = time.time()
        # 여기에 구현
        result = func(*args, **kwargs)
        # 여기에 구현 (실행 시간 출력)
        return result
    return wrapper

def memoize(func):
    """함수 결과를 캐싱하는 decorator"""
    cache = {}  # 결과 저장용 딕셔너리
    
    def wrapper(*args):
        # 여기에 구현
        # 힌트: args가 cache에 있으면 저장된 값 반환
        # 없으면 함수 실행 후 결과를 cache에 저장
        pass
    
    return wrapper

# 테스트용 함수
@timer
@memoize
def fibonacci(n):
    """재귀적 피보나치 (느린 버전)"""
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

# 테스트
print(fibonacci(10))  # 첫 실행 - 느림
print(fibonacci(10))  # 두 번째 실행 - 캐시에서 즉시 반환
print(fibonacci(15))  # 다른 값

추가 도전: - 캐시 크기 제한 추가 - 캐시 통계 (히트/미스) 출력 - 특정 시간 후 캐시 만료

import time

def timer(func):
    """함수 실행 시간을 측정하는 decorator"""
    def wrapper(*args, **kwargs):
        start_time = time.time()
        # 여기에 구현
        result = func(*args, **kwargs)
        # 여기에 구현 (실행 시간 출력)
        return result
    return wrapper

def memoize(func):
    """함수 결과를 캐싱하는 decorator"""
    cache = {}  # 결과 저장용 딕셔너리
    
    def wrapper(*args):
        # 여기에 구현
        # 힌트: args가 cache에 있으면 저장된 값 반환
        # 없으면 함수 실행 후 결과를 cache에 저장
        pass
    
    return wrapper

# 여기에 추가 코드 작성


Chapter 8: Control flow
Chapter 14: Exceptions

This work © 2025 by Sungkyun Cho is licensed under CC BY-NC-SA 4.0