<문제1> : 가변 인자를 활용한 평균 계산기
- 설명 : 여러 개의 숫자를 입력받아 평균을 계산하는 함수 calculate_average를 작성
- 요구사항
1. 숫자가 하나도 전달되지 않았을 경우 "입력된 숫자가 없습니다."라는 메시지를 반환
2. 입력된 모든 숫자의 평균을 계산하여 소수점 2자리까지 반올림한 결과를 반환
3. 함수 설명을 위한 적절한 docstring을 포함
- 구현 코드
def calculate_average(*nums) :
"""
전달받은 숫자의 평균을 반환하는 함수
*nums : 가변 위치 인자로 임의의 개수를 인자로 받고, 함수 내에서 튜플로 처리된다.
len(nums)를 통해 빈 튜플인지 확인하여 입력 숫자가 없을 때 문장을 출력한다.
다음 순서로 total과 average에 각각의 연산값을 담아 round함수를 통해 소수점 1자리 까지만 표현한다.
"""
if len(nums) == 0:
return "입력된 숫자가 없습니다."
total = sum(nums)
average = total / len(nums)
return round(average, 2)
print(calculate_average())
<문제2> : 키워드 인자를 활용한 학생 정보 출력
- 설명 : 학생의 정보를 입력받아 형식에 맞게 출력하는 함수 print_student_info를 작성
- 요구사항
1. 기본적으로 학생 정보에 '이름'과 '나이'는 반드시 입력
2. '이름'이나 '나이'가 전달되지 않은 경우 "필수 정보가 누락되었습니다."라는 메시지를 반환
3.모든 학생 정보를 "키: 값" 형태로 한 줄씩 출력하고, 마지막에 총 정보 개수를 반환
- 구현 코드
def print_student_info(**info) :
"""
학생 정보를 딕셔너리 형태로 반환하는 함수이다.
**info를 통해 임의의 키워드 인자를 딕셔너리 형태로 담을 것이다.
'이름', '나이'가 info에 없는 경우(key값에 없는 경우) 문자열을 반환한다.
info.items()를 출력 시 return없이 함수가 끝날 경우 None이 반환 따라서
result에 값을 담아주어 표현한다. 이때 리스트 형식으로 담으면 출력상 []가 나올 수 있으니
문자형으로 선언 후 결합하는 형식으로 담는다.
"""
if "이름" not in info.keys() or "나이" not in info.keys():
return "필수 정보가 누락되었습니다."
result = ""
for key, value in info.items():
result += f"- {key}: {value}\n"
result += f"총 정보 개수: {len(info)}"
return result
<문제3> : 람다 함수와 sorted를 활용한 정렬
- 설명 : 학생들의 성적 정보가 담긴 리스트를 다양한 기준으로 정렬하는 함수 sort_students를 작성
- 요구사항
1. “학생 정보” 리스트와 “정렬 기준(criterion)”을 매개변수로 하는 함수 제작
2. “학생 정보”는 딕셔너리 형태로, '이름', '국어', '영어', '수학' 의 4개의 키가 있음.
3. “정렬 기준”은 '이름', '국어', '영어', '수학', '총점’ 으로 5개
4. 잘못된 “정렬 기준”이 입력되면 "잘못된 정렬 기준입니다."를 반환
- 구현 코드
def sort_students(students, criterion):
"""
1. 학생 정보 리스트와 정렬 기준(criterion)의 2개의 매개변수로 받는다.
2. 학생 정보 리스트의 1개의 요소에는 딕셔너리 형태로 구성
-'이름', '국어', '영어', '수학' 키와 그에 해당하는 점수를 벨류로 갖는다.
3. 정렬 기준은 리스트의 키 값과 '총점'(키값의 벨류들의 합)으로 총 5개
4. 리스트 형태로 정렬된 값을 반환한다. 이때 정렬 기준이 잘못되면 문자열 반환
"""
if criterion not in ('이름', '국어', '영어', '수학', '총점'):
return "잘못된 정렬 기준입니다."
if criterion == '총점':
return sorted(students, key=lambda X: X['국어'] + X['영어'] + X['수학'])
else:
return sorted(students, key=lambda X: X[criterion])
students = [
{'이름': '김철수', '국어': 90, '영어': 80, '수학': 85},
{'이름': '이영희', '국어': 85, '영어': 95, '수학': 90},
{'이름': '박민수', '국어': 95, '영어': 85, '수학': 75}
]
print(sort_students(students, '이름'))
print(sort_students(students, '총점'))
print(sort_students(students, '과학'))
<문제4> : 클로저 내부 함수와 nonlocal을 활용한 카운터 함수
- 설명 : 호출 횟수를 카운트하면서 메시지를 출력하는 함수 create_counter를 작성
- 요구사항
1. 문자열 `message`를 매개변수 매개변수로 하는 함수 제작
2. 함수 내부에 `counter` 함수를 정의하고, 이를 반환
3. `counter` 함수는 호출될 때마다 호출 횟수와 함께 전달된 메시지를 출력
4. `counter` 함수는 현재 호출 횟수를 반환
- 구현 코드
def create_counter(message):
"""
create_counter 함수는 message 를 매개변수로 받아 현재 호출 횟수와 메시지, 반환 횟수를 반환하는 외부 함수이다.
- 카운팅을 위해 외부함수의 변수에 count를 선언 내부함수 counter를 호출하고 함수 내용을 종료한다.
counter() 함수는 호출 횟수와 메시지, 반환 횟수를 반환하는 내부 함수이다.
- print문으로 호출될 시 그 None 출력을 방지하기 위해 문자열 반환으로 함수를 종료한다.
"""
count = 0
def counter():
nonlocal count
count += 1
return f"호출 {count}: {message} / 반환 : {count}"
return counter
my_counter = create_counter("안녕하세요!")
print(my_counter())
print(my_counter())
print(my_counter())
print(my_counter())
<문제1> : 기본 클래스 구현
- 설명 : 클래스의 기본 구조와 인스턴스 생성
- 요구사항
1.`Book` 클래스 제작
> 클래스 속성 : “제목(title)”, “저자(author)”, “출판년도(year)”, “가격(price)”
2. 메서드 구현
> `__init__`: 모든 속성을 초기화
> `__str__`: "제목 (저자, 출판년도)" 형식의 문자열 반환
> `get_age`: 현재 연도(2025)를 기준으로 책의 나이를 계산하여 반환
> `apply_discount`: 인자로 할인율(%)을 받아, 할인된 가격을 반환
- 구현 코드
class book:
"""
book의 제목(title), 저자(author), 출판년도(year), 가격(price)를 속성으로 하는 클래스
"""
def __init__(self, title, author, year, price):
self.title = title
self.author = author
self.year = year
self.price = price
def __str__(self):
"""책 정보"""
return f"책 정보 : {self.title}, ({self.author}, {self.year})"
def get_age(self):
"""책 나이"""
book_age = 2025 - self.year
return f"책 나이 : {book_age}"
def apply_dicount(self, discount_rate):
"""할인율(%) 적용 가격"""
discount_price = self.price*(1-discount_rate/100)
return round(discount_price, 2)
pass
book1 = book("제목", "저자", 2020, 15000)
print(book1)
print(book1.get_age())
print("할인가:", book1.apply_dicount(50))
<문제2> : 클래스 변수와 인스턴스 변수
- 설명 : 클래스 변수와 인스턴스 변수의 차이 확인
- 요구사항
1. Student 클래스 구현
- 클래스 변수 : `school_name`(학교명), `total_students`(총 학생 수)
- 인스턴스 변수 : `name`(이름), `grade`(학년), `scores`(과목별 점수 딕셔너리)
2. 다음의 메서드들을 구현
- `__init__`: 이름과 학년을 초기화하고, `total_students`를 1 증가
- `add_score`: 과목명과 점수를 받아 scores 딕셔너리에 추가
- `get_average`: 모든 과목의 평균 점수 계산
- `__str__`: "이름 (학년) - 평균: 평균점수" 형식의 문자열 반환
- 클래스 메서드 `get_school_info`: 학교명과 총 학생 수 정보를 문자열로 반환
- 구현 코드
class Student:
"""학교명은 직접 수정해야 합니다."""
school_name = "???학교"
total_students = 0
def __init__(self, name, grade):
self.name = name
self.grade = grade
self.scores = {}
Student.total_students += 1
def add_score(self, subject, score):
self.scores[subject] = score
def get_average(self):
if len(self.scores) == 0:
return 0
return sum(self.scores.values())/len(self.scores)
def __str__(self):
AVG = self.get_average()
return f"{self.name} ({self.grade}학년) - 평균 : {AVG:.2f}"
@classmethod
def get_school_info(cls):
return f"{cls.school_name} - 총 학생 수: {cls.total_students}명"
<문제3> : 특수 메서드 구현
- 설명 : 특수 메서드 활용
- 요구사항
1. Vector2D 클래스 구현
- 2차원 벡터의 x, y 좌표를 저장
2. 특수 메서드 구현
- `__init__`: x, y 좌표 초기화
- `__str__`: "(x, y)" 형식의 문자열 반환
- `__repr__`: "Vector2D(x, y)" 형식의 문자열 반환
- `__add__`: 두 벡터의 덧셈 (좌표별 덧셈)
- `__sub__`: 두 벡터의 뺄셈 (좌표별 뺄셈)
- `__mul__`: 벡터와 스칼라의 곱셈 (각 좌표에 스칼라 곱)
- `__eq__`: 두 벡터가 같은지 비교 (x, y 좌표가 모두 같아야 함)
- `__len__`: 벡터의 길이(원점에서의 거리)를 정수로 반환
- 구현 코드
""" 좌표별 연산의 경우 x1과 x2가 둘 중 누가 클지 모름
그러나 결국 연산이라는 점, 그 위치가 어디로 들어가도 동일한 값이 나와야 한다는 점에서
type_error보다 NorImplemented를 사용하여 연산 방향이 X1 -> X2 로 하다 연산오류일 시
X2 -> X1으로 자동으로 바꿔준다!
"""
class Vector2D:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f"({self.x}, {self.y})"
def __repr__(self):
return f"Vector2D({self.x}, {self.y})"
def __add__(self, other):
if isinstance(other, Vector2D):
return Vector2D(self.x + other.x, self.y + other.y)
return NotImplemented
def __sub__(self, other):
if isinstance(other, Vector2D):
return Vector2D(self.x - other.x, self.y - other.y)
return NotImplemented
def __mul__(self, scalar):
if isinstance(scalar, (int, float)):
return Vector2D(self.x * scalar, self.y * scalar)
return NotImplemented
def __eq__(self, other):
if isinstance(other, Vector2D):
return self.x == other.x and self.y == other.y
return False
def __len__(self):
return int(((self.x**2)+(self.y**2))**0.5)
<문제4> : 클래스 상속
- 설명 : 클래스 상속과 메서드 오버라이딩
- 요구사항
1. `Shape` 클래스를 상속받는 `Circle`(원) 클래스를 구현
- 추가 속성: `radius`(반지름)
- 오버라이드 메서드
A. `__init__`: 부모 초기화 + 반지름 초기화
B. `area`: 원의 넓이 계산 (π × r²)
C. `perimeter`: 원의 둘레 계산 (2 × π × r)
D. `describe`: "이것은 반지름이 r인 원입니다." 형식 문자열 반환
2. `Shape` 클래스를 상속받는 `Rectangle`(직사각형) 클래스를 구현
- 추가 속성: `width`(너비), `height`(높이)
- 오버라이드 메서드:
A. `__init__`: 부모 초기화 + 너비와 높이 초기화
B. `area`: 직사각형의 넓이 계산 (너비 × 높이)
C. `perimeter`: 직사각형의 둘레 계산 (2 × (너비 + 높이))
D. `describe`: "이것은 너비가 width, 높이가 height인 직사각형입니다." 형식 문자열 반환
- 추가 메서드:
A. `is_square`: 정사각형인지 확인 (너비와 높이가 같으면 True, 다르면 False 반환)
3. `Rectangle` 클래스를 상속받는 `Cuboid`(직육면체) 클래스를 구현
- 추가 속성: `depth`(깊이)
- 오버라이드 메서드
A. `__init__`: 부모 초기화 + 깊이 초기화
B. `area`: 직육면체의 표면적 계산 (2 × (너비 × 높이 + 너비 × 깊이 + 높이 × 깊이))
C. `describe`: "이것은 너비가 width, 높이가 height, 깊이가 depth인 직육면체입니다." 형식 문자열 반환
- 추가 메서드
A. `volume`: 직육면체의 부피 계산 (너비 × 높이 × 깊이)
B.`is_cube`: 정육면체인지 확인 (너비, 높이, 깊이가 모두 같으면 True, 다르면 False 반환)
<기본 클래스(Shape) 코드>
import math
class Shape:
"""도형을 표현하는 기본 클래스"""
def __init__(self, name):
"""도형 초기화"""
self.name = name
def area(self):
"""도형의 넓이를 계산"""
return 0
def perimeter(self):
"""도형의 둘레(또는 표면적)를 계산"""
return 0
def describe(self):
"""도형에 대한 설명"""
return f"이것은 {self.name} 도형입니다."
def __str__(self):
"""도형의 문자열 표현"""
return f"{self.name} (면적: {self.area()}, 둘레: {self.perimeter()})"
<코드 구현1 : Circle 클래스>
# 1. Circle 클래스
class Circle(Shape):
def __init__(self, radius):
super().__init__("원")
self.radius = radius
def area(self):
return math.pi * self.radius**2
def perimeter(self):
return 2 * math.pi * self.radius
def describe(self):
return f"이것은 반지름이 {self.radius}인 원입니다."
<코드 구현2 : Rectangle 클래스>
# 2. Rectangle 클래스
class Rectangle(Shape):
def __init__(self, width, height):
super().__init__("직사각형")
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
def describe(self):
return f"이것은 너비가 {self.width}, 높이가 {self.height}인 직사각형입니다."
def is_square(self):
return self.width == self.height
<코드 구현3 : Cuboid 클래스>
# 3. Cuboid 클래스
class Cuboid(Rectangle):
def __init__(self, width, height, depth):
super().__init__(width, height)
self.name = "직육면체" # Shape 클래스의 name 재설정
self.depth = depth
def area(self):
w, h, d = self.width, self.height, self.depth
return 2 * (w * h + w * d + h * d)
def describe(self):
return f"이것은 너비가 {self.width}, 높이가 {self.height}, 깊이가 {self.depth}인 직육면체입니다."
def volume(self):
return self.width * self.height * self.depth
def is_cube(self):
return self.width == self.height == self.depth