Day 31에서 클래스를 만들었는데, 매번 객체 만들고 속성 설정하는 게 번거롭죠? 🤔 ──car = Car() 후에 car.color = "빨강", car.speed = 0… 이렇게 하나씩 설정하는 건 비효율적입니다! 😊
자동차 공장에서 차를 만들 때 생각해보세요. 바퀴, 엔진, 핸들을 나중에 하나씩 조립하는 게 아니라, “소나타 한 대!”라고 주문하면 완성된 차가 나오잖아요?
Python의 __init__()이 바로 이 역할을 합니다! 객체 생성과 동시에 필요한 모든 초기값을 자동으로 설정하는 “생성자”입니다! 💡
🎯 오늘의 학습 목표
⭐⭐⭐ (30-40분 완독)
📚 사전 지식
🎯 학습 목표 1: 생성자(init)의 역할 이해하기
생성자(Constructor)는 객체가 생성될 때 자동으로 호출되는 특별한 메서드입니다.
🏭 실생활 비유: 자동차 공장
자동차를 만들 때:
1
2
3
4
5
6
| # 생성자 없이 (Day 31 방식)
car = Car() # 빈 자동차 생성
car.set_info("현대", "소나타", 2024) # 나중에 정보 설정
# 생성자 사용 (Day 32 방식)
car = Car("현대", "소나타", 2024) # 생성과 동시에 정보 설정! ✨
|
장점:
- 객체 생성 즉시 필요한 데이터 설정
- 코드가 간결해짐
- 잘못된 상태의 객체 생성 방지
🎯 학습 목표 2: 인스턴스 초기화 방법 배우기
init 메서드
기본 문법
1
2
3
4
5
| class ClassName:
def __init__(self, param1, param2):
"""생성자: 객체 초기화"""
self.attribute1 = param1
self.attribute2 = param2
|
특징:
__init__: 언더스코어 2개 + init + 언더스코어 2개 - 객체 생성 시 자동 호출됨
- 반환값(return)이 없음
- 첫 번째 매개변수는 항상
self
Before & After 비교
Before (Day 31 방식)
1
2
3
4
5
6
7
8
9
10
11
12
| class Dog:
def set_info(self, name, age):
self.name = name
self.age = age
def bark(self):
return f"{self.name}: 멍멍!"
# 2단계 과정
dog = Dog() # 1. 객체 생성
dog.set_info("멍멍이", 3) # 2. 정보 설정
print(dog.bark())
|
After (Day 32 방식) ✅
1
2
3
4
5
6
7
8
9
10
11
12
| class Dog:
def __init__(self, name, age):
"""생성자: 강아지 정보 초기화"""
self.name = name
self.age = age
def bark(self):
return f"{self.name}: 멍멍!"
# 1단계로 완료!
dog = Dog("멍멍이", 3) # 생성과 동시에 초기화
print(dog.bark())
|
실행 결과:
📝 생성자 활용 예제
예제 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
| class Student:
"""학생 정보를 관리하는 클래스"""
school_name = "파이썬 고등학교"
def __init__(self, name, student_id, grade):
"""생성자: 학생 정보 초기화"""
print(f"🎓 {name} 학생이 등록되었습니다!")
self.name = name
self.student_id = student_id
self.grade = grade
self.scores = [] # 빈 리스트로 초기화
def add_score(self, subject, score):
"""과목 성적 추가"""
self.scores.append({
"subject": subject,
"score": score
})
def get_average(self):
"""평균 성적 계산"""
if not self.scores:
return 0
total = sum(item["score"] for item in self.scores)
return total / len(self.scores)
def print_report(self):
"""성적표 출력"""
print(f"\n{'='*40}")
print(f"학교: {Student.school_name}")
print(f"이름: {self.name} ({self.student_id})")
print(f"학년: {self.grade}학년")
print(f"{'-'*40}")
if self.scores:
print("과목별 성적:")
for item in self.scores:
print(f" - {item['subject']}: {item['score']}점")
print(f"{'-'*40}")
print(f"평균: {self.get_average():.2f}점")
else:
print("등록된 성적이 없습니다.")
print(f"{'='*40}\n")
# 사용 - 훨씬 간결해졌습니다!
student1 = Student("홍길동", "2024001", 2)
student1.add_score("수학", 95)
student1.add_score("영어", 88)
student1.add_score("과학", 92)
student1.print_report()
student2 = Student("김철수", "2024002", 2)
student2.add_score("수학", 78)
student2.add_score("영어", 85)
student2.print_report()
|
실행 결과:
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
| 🎓 홍길동 학생이 등록되었습니다!
🎓 김철수 학생이 등록되었습니다!
========================================
학교: 파이썬 고등학교
이름: 홍길동 (2024001)
학년: 2학년
----------------------------------------
과목별 성적:
- 수학: 95점
- 영어: 88점
- 과학: 92점
----------------------------------------
평균: 91.67점
========================================
========================================
학교: 파이썬 고등학교
이름: 김철수 (2024002)
학년: 2학년
----------------------------------------
과목별 성적:
- 수학: 78점
- 영어: 85점
----------------------------------------
평균: 81.50점
========================================
|
예제 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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
| class BankAccount:
"""은행 계좌를 관리하는 클래스"""
bank_name = "파이썬 은행"
interest_rate = 0.02 # 연 2% 이자
def __init__(self, owner, account_number, balance=0):
"""생성자: 계좌 정보 초기화"""
print(f"💰 {owner}님의 계좌가 개설되었습니다!")
print(f" 계좌번호: {account_number}")
print(f" 초기 잔액: {balance:,}원\n")
self.owner = owner
self.account_number = account_number
self.balance = balance
self.transactions = [] # 거래 내역
def deposit(self, amount):
"""입금"""
if amount <= 0:
return "입금액은 0보다 커야 합니다."
self.balance += amount
self.transactions.append(f"입금: +{amount:,}원")
return f"{amount:,}원이 입금되었습니다. (잔액: {self.balance:,}원)"
def withdraw(self, amount):
"""출금"""
if amount <= 0:
return "출금액은 0보다 커야 합니다."
if amount > self.balance:
return f"잔액이 부족합니다. (현재 잔액: {self.balance:,}원)"
self.balance -= amount
self.transactions.append(f"출금: -{amount:,}원")
return f"{amount:,}원이 출금되었습니다. (잔액: {self.balance:,}원)"
def apply_interest(self):
"""이자 적용"""
interest = int(self.balance * BankAccount.interest_rate)
self.balance += interest
self.transactions.append(f"이자: +{interest:,}원")
return f"이자 {interest:,}원이 적용되었습니다. (잔액: {self.balance:,}원)"
def get_balance(self):
"""잔액 조회"""
return f"{self.owner}님의 잔액: {self.balance:,}원"
def print_statement(self):
"""거래 내역 출력"""
print(f"\n{'='*50}")
print(f"{BankAccount.bank_name} - 거래 내역서")
print(f"{'='*50}")
print(f"예금주: {self.owner}")
print(f"계좌번호: {self.account_number}")
print(f"{'-'*50}")
if self.transactions:
print("거래 내역:")
for i, transaction in enumerate(self.transactions, 1):
print(f" {i}. {transaction}")
else:
print("거래 내역이 없습니다.")
print(f"{'-'*50}")
print(f"현재 잔액: {self.balance:,}원")
print(f"{'='*50}\n")
# 사용
account1 = BankAccount("홍길동", "123-456-789", 100000)
print(account1.deposit(50000))
print(account1.withdraw(20000))
print(account1.apply_interest())
account1.print_statement()
account2 = BankAccount("김철수", "987-654-321") # 초기 잔액 0원
print(account2.deposit(1000000))
account2.print_statement()
|
실행 결과:
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
| 💰 홍길동님의 계좌가 개설되었습니다!
계좌번호: 123-456-789
초기 잔액: 100,000원
💰 김철수님의 계좌가 개설되었습니다!
계좌번호: 987-654-321
초기 잔액: 0원
50,000원이 입금되었습니다. (잔액: 150,000원)
20,000원이 출금되었습니다. (잔액: 130,000원)
이자 2,600원이 적용되었습니다. (잔액: 132,600원)
==================================================
파이썬 은행 - 거래 내역서
==================================================
예금주: 홍길동
계좌번호: 123-456-789
--------------------------------------------------
거래 내역:
1. 입금: +50,000원
2. 출금: -20,000원
3. 이자: +2,600원
--------------------------------------------------
현재 잔액: 132,600원
==================================================
1,000,000원이 입금되었습니다. (잔액: 1,000,000원)
==================================================
파이썬 은행 - 거래 내역서
==================================================
예금주: 김철수
계좌번호: 987-654-321
--------------------------------------------------
거래 내역:
1. 입금: +1,000,000원
--------------------------------------------------
현재 잔액: 1,000,000원
==================================================
|
예제 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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
| class Character:
"""게임 캐릭터를 표현하는 클래스"""
def __init__(self, name, char_class, level=1):
"""생성자: 캐릭터 초기화"""
print(f"⚔️ '{name}' 캐릭터가 생성되었습니다!")
print(f" 직업: {char_class}")
print(f" 레벨: {level}\n")
self.name = name
self.char_class = char_class
self.level = level
# 직업별 초기 스탯 설정
if char_class == "전사":
self.hp = 150
self.max_hp = 150
self.attack = 20
elif char_class == "마법사":
self.hp = 100
self.max_hp = 100
self.attack = 30
elif char_class == "궁수":
self.hp = 120
self.max_hp = 120
self.attack = 25
else:
self.hp = 100
self.max_hp = 100
self.attack = 15
self.exp = 0
self.exp_to_next_level = 100
def take_damage(self, damage):
"""피해 입기"""
self.hp = max(0, self.hp - damage)
if self.hp == 0:
return f"💀 {self.name}이(가) 쓰러졌습니다!"
else:
return f"⚔️ {self.name}이(가) {damage}의 피해를 입었습니다. (HP: {self.hp}/{self.max_hp})"
def heal(self, amount):
"""회복"""
old_hp = self.hp
self.hp = min(self.max_hp, self.hp + amount)
healed = self.hp - old_hp
return f"💚 {self.name}이(가) {healed}만큼 회복했습니다. (HP: {self.hp}/{self.max_hp})"
def gain_exp(self, exp):
"""경험치 획득"""
self.exp += exp
message = f"✨ {self.name}이(가) {exp} 경험치를 획득했습니다."
# 레벨업 체크
if self.exp >= self.exp_to_next_level:
self.level_up()
message += f"\n🎉 레벨 업! {self.name}의 레벨이 {self.level}이 되었습니다!"
return message
def level_up(self):
"""레벨업"""
self.level += 1
self.exp -= self.exp_to_next_level
self.exp_to_next_level = int(self.exp_to_next_level * 1.5)
# 스탯 증가 (직업별)
if self.char_class == "전사":
self.max_hp += 30
self.attack += 3
elif self.char_class == "마법사":
self.max_hp += 20
self.attack += 5
elif self.char_class == "궁수":
self.max_hp += 25
self.attack += 4
else:
self.max_hp += 20
self.attack += 2
self.hp = self.max_hp
def get_status(self):
"""상태 확인"""
status = f"""
{'='*40}
[캐릭터 정보]
이름: {self.name}
직업: {self.char_class}
레벨: {self.level}
HP: {self.hp}/{self.max_hp}
공격력: {self.attack}
경험치: {self.exp}/{self.exp_to_next_level}
{'='*40}
"""
return status.strip()
# 사용 - 직업별로 다른 초기 스탯!
warrior = Character("용사", "전사")
print(warrior.get_status())
print("\n" + "="*40 + "\n")
mage = Character("마법사", "마법사", level=5)
print(mage.get_status())
print("\n" + "="*40 + "\n")
archer = Character("궁수", "궁수")
print(archer.take_damage(30))
print(archer.heal(15))
print(archer.gain_exp(120))
print("\n" + archer.get_status())
|
실행 결과:
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
| ⚔️ '용사' 캐릭터가 생성되었습니다!
직업: 전사
레벨: 1
========================================
[캐릭터 정보]
이름: 용사
직업: 전사
레벨: 1
HP: 150/150
공격력: 20
경험치: 0/100
========================================
========================================
⚔️ '마법사' 캐릭터가 생성되었습니다!
직업: 마법사
레벨: 5
========================================
[캐릭터 정보]
이름: 마법사
직업: 마법사
레벨: 5
HP: 100/100
공격력: 30
경험치: 0/100
========================================
========================================
⚔️ '궁수' 캐릭터가 생성되었습니다!
직업: 궁수
레벨: 1
⚔️ 궁수이(가) 30의 피해를 입었습니다. (HP: 90/120)
💚 궁수이(가) 15만큼 회복했습니다. (HP: 105/120)
✨ 궁수이(가) 120 경험치를 획득했습니다.
🎉 레벨 업! 궁수의 레벨이 2이 되었습니다!
========================================
[캐릭터 정보]
이름: 궁수
직업: 궁수
레벨: 2
HP: 145/145
공격력: 29
경험치: 20/150
========================================
|
🎨 기본값을 가진 생성자
생성자 매개변수에 기본값을 설정할 수 있습니다.
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
| class Product:
"""상품 정보를 관리하는 클래스"""
def __init__(self, name, price, quantity=1, category="기타"):
"""생성자: 상품 정보 초기화"""
self.name = name
self.price = price
self.quantity = quantity
self.category = category
def get_total_price(self):
"""총 가격 계산"""
return self.price * self.quantity
def print_info(self):
"""상품 정보 출력"""
print(f"{'='*40}")
print(f"상품명: {self.name}")
print(f"카테고리: {self.category}")
print(f"단가: {self.price:,}원")
print(f"수량: {self.quantity}개")
print(f"총 가격: {self.get_total_price():,}원")
print(f"{'='*40}\n")
# 다양한 방식으로 생성 가능
product1 = Product("노트북", 1500000, 2, "전자제품")
product1.print_info()
product2 = Product("마우스", 30000) # quantity=1, category="기타"
product2.print_info()
product3 = Product("키보드", 80000, category="전자제품") # quantity=1
product3.print_info()
|
실행 결과:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| ========================================
상품명: 노트북
카테고리: 전자제품
단가: 1,500,000원
수량: 2개
총 가격: 3,000,000원
========================================
========================================
상품명: 마우스
카테고리: 기타
단가: 30,000원
수량: 1개
총 가격: 30,000원
========================================
========================================
상품명: 키보드
카테고리: 전자제품
단가: 80,000원
수량: 1개
총 가격: 80,000원
========================================
|
🎯 학습 목표 3: 소멸자(del)의 동작 원리 알기
소멸자(Destructor)는 객체가 메모리에서 삭제될 때 자동으로 호출되는 메서드입니다.
기본 문법
1
2
3
4
5
6
7
8
9
| class ClassName:
def __init__(self, name):
"""생성자"""
self.name = name
print(f"✨ {self.name} 생성")
def __del__(self):
"""소멸자"""
print(f"💀 {self.name} 소멸")
|
소멸자 동작 예시
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
| class FileHandler:
"""파일 핸들러 클래스"""
def __init__(self, filename):
"""생성자: 파일 정보 설정"""
self.filename = filename
print(f"📂 {filename} 핸들러 생성")
def __del__(self):
"""소멸자: 리소스 정리"""
print(f"🗑️ {self.filename} 핸들러 정리 중...")
print(f" - 파일 연결 종료")
print(f" - 메모리 해제")
# 사용
print("프로그램 시작")
handler1 = FileHandler("data.txt")
handler2 = FileHandler("config.json")
print("\n작업 수행 중...\n")
# 명시적 삭제
del handler1
print("\n프로그램 종료")
# 프로그램 종료 시 handler2 자동 삭제
|
실행 결과:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| 프로그램 시작
📂 data.txt 핸들러 생성
📂 config.json 핸들러 생성
작업 수행 중...
🗑️ data.txt 핸들러 정리 중...
- 파일 연결 종료
- 메모리 해제
프로그램 종료
🗑️ config.json 핸들러 정리 중...
- 파일 연결 종료
- 메모리 해제
|
소멸자 실전 예제: 데이터베이스 연결
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
| class DatabaseConnection:
"""데이터베이스 연결을 관리하는 클래스"""
connection_count = 0
def __init__(self, host, database):
"""생성자: 데이터베이스 연결"""
self.host = host
self.database = database
self.is_connected = True
DatabaseConnection.connection_count += 1
print(f"🔗 데이터베이스 연결 성공!")
print(f" 호스트: {self.host}")
print(f" 데이터베이스: {self.database}")
print(f" 현재 연결 수: {DatabaseConnection.connection_count}\n")
def query(self, sql):
"""쿼리 실행"""
if not self.is_connected:
return "❌ 연결이 끊어졌습니다."
return f"✅ 쿼리 실행: {sql}"
def close(self):
"""연결 종료"""
if self.is_connected:
self.is_connected = False
DatabaseConnection.connection_count -= 1
print(f"🔌 {self.database} 연결 종료")
def __del__(self):
"""소멸자: 리소스 정리"""
if self.is_connected:
print(f"⚠️ 자동 정리: {self.database} 연결 종료")
DatabaseConnection.connection_count -= 1
print(f" 현재 연결 수: {DatabaseConnection.connection_count}")
# 사용
print("=" * 50)
db1 = DatabaseConnection("localhost", "users_db")
print(db1.query("SELECT * FROM users"))
db2 = DatabaseConnection("localhost", "products_db")
print(db2.query("SELECT * FROM products"))
print("\n" + "=" * 50)
print("db1 명시적 종료")
print("=" * 50 + "\n")
db1.close()
del db1
print("\n" + "=" * 50)
print("프로그램 종료 (db2 자동 정리)")
print("=" * 50 + "\n")
|
실행 결과:
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
| ==================================================
🔗 데이터베이스 연결 성공!
호스트: localhost
데이터베이스: users_db
현재 연결 수: 1
✅ 쿼리 실행: SELECT * FROM users
🔗 데이터베이스 연결 성공!
호스트: localhost
데이터베이스: products_db
현재 연결 수: 2
✅ 쿼리 실행: SELECT * FROM products
==================================================
db1 명시적 종료
==================================================
🔌 users_db 연결 종료
현재 연결 수: 1
==================================================
프로그램 종료 (db2 자동 정리)
==================================================
⚠️ 자동 정리: products_db 연결 종료
현재 연결 수: 0
|
🎯 학습 목표 4: 생성자와 소멸자 활용하기
소멸자 사용 시 주의사항
1. 소멸자는 예측 불가능
Python의 가비지 컬렉터가 언제 소멸자를 호출할지 보장할 수 없습니다.
1
2
3
4
5
6
7
8
9
10
11
12
| class Resource:
def __init__(self, name):
self.name = name
print(f"✨ {name} 생성")
def __del__(self):
print(f"💀 {name} 소멸") # 언제 호출될지 모름!
# 소멸 시점을 정확히 예측할 수 없음
res1 = Resource("리소스1")
res2 = Resource("리소스2")
# 프로그램 종료 시점에 어떤 순서로 소멸될지 모름
|
2. 명시적 정리 메서드 사용 권장 ✅
리소스 정리가 중요한 경우, 소멸자 대신 명시적 메서드를 사용하세요!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| class FileManager:
def __init__(self, filename):
self.filename = filename
print(f"📂 {filename} 열기")
def close(self): # ✅ 명시적 정리 메서드
"""파일 닫기"""
print(f"🔒 {self.filename} 닫기")
def __del__(self):
"""소멸자: 백업 정리"""
print(f"🗑️ {self.filename} 소멸자 호출 (백업)")
# 사용
manager = FileManager("data.txt")
# ... 작업 ...
manager.close() # ✅ 명시적으로 정리
|
3. Context Manager 사용 (권장) ⭐
Python의 with 문과 함께 사용하면 자동으로 정리됩니다. (Day 55에서 자세히 배웁니다!)
1
2
3
4
| # 미리보기 (나중에 자세히!)
with open("data.txt", "r") as file:
content = file.read()
# with 블록 종료 시 자동으로 파일 닫힘!
|
💡 실전 팁 & 주의사항
Tip 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
| # ❌ 나쁜 예
class DataProcessor:
def __init__(self, filename):
# 생성자에서 복잡한 작업 수행
with open(filename) as f: # 파일이 없으면 에러!
self.data = f.read()
self.process_data() # 시간이 오래 걸림
# ✅ 좋은 예
class DataProcessor:
def __init__(self, filename):
# 생성자는 간단하게
self.filename = filename
self.data = None
def load_data(self):
# 별도 메서드로 분리
with open(self.filename) as f:
self.data = f.read()
def process_data(self):
# 별도 메서드로 분리
if self.data:
# 데이터 처리
pass
|
Tip 2: 소멸자보다 명시적 정리 메서드 사용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| # ✅ 권장하는 방식
class DatabaseConnection:
def __init__(self, host, port):
self.host = host
self.port = port
self.connected = False
def connect(self):
"""명시적 연결"""
self.connected = True
print(f"✅ {self.host}:{self.port} 연결")
def disconnect(self):
"""명시적 종료"""
self.connected = False
print(f"❌ {self.host}:{self.port} 연결 종료")
# 사용
db = DatabaseConnection("localhost", 5432)
db.connect()
# 작업 수행
db.disconnect() # 명시적으로 정리
|
Tip 3: 기본값은 불변 객체로
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| # ❌ 위험한 예 - 가변 객체를 기본값으로
class Student:
def __init__(self, name, scores=[]): # ❌ 모든 인스턴스가 같은 리스트 공유!
self.name = name
self.scores = scores
s1 = Student("홍길동")
s1.scores.append(90)
s2 = Student("김철수")
print(s2.scores) # [90] - 원치 않는 공유 발생!
# ✅ 올바른 예
class Student:
def __init__(self, name, scores=None): # None 사용
self.name = name
self.scores = scores if scores is not None else []
s1 = Student("홍길동")
s1.scores.append(90)
s2 = Student("김철수")
print(s2.scores) # [] - 독립적인 리스트
|
🧪 연습 문제
문제 1: 직원 관리 클래스
다음 요구사항을 만족하는 Employee 클래스를 작성하세요:
요구사항:
- 생성자로 이름, 부서, 연봉 초기화
- 연봉 인상 메서드 (인상률 %)
- 직원 정보 출력 메서드
- 클래스 속성으로 총 직원 수 관리
1
2
3
4
5
6
7
8
9
| # 사용 예시
emp1 = Employee("홍길동", "개발팀", 50000000)
emp2 = Employee("김철수", "디자인팀", 45000000)
emp1.print_info()
emp1.raise_salary(10)
emp1.print_info()
print(f"\n총 직원 수: {Employee.get_employee_count()}명")
|
예상 출력:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| ✨ 홍길동님이 입사했습니다!
✨ 김철수님이 입사했습니다!
========================================
이름: 홍길동
부서: 개발팀
연봉: 50,000,000원
========================================
💰 연봉이 10% 인상되었습니다!
========================================
이름: 홍길동
부서: 개발팀
연봉: 55,000,000원
========================================
총 직원 수: 2명
|
💡 힌트
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| class Employee:
employee_count = 0 # 클래스 속성
def __init__(self, name, department, salary):
# 인스턴스 속성 초기화
# employee_count 증가
pass
def raise_salary(self, rate):
# 연봉 = 연봉 * (1 + rate/100)
pass
def print_info(self):
# 직원 정보 출력
pass
@classmethod
def get_employee_count(cls):
return cls.employee_count
|
✅ 정답
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
| class Employee:
"""직원 정보를 관리하는 클래스"""
employee_count = 0 # 클래스 속성
def __init__(self, name, department, salary):
"""생성자: 직원 정보 초기화"""
print(f"✨ {name}님이 입사했습니다!")
self.name = name
self.department = department
self.salary = salary
Employee.employee_count += 1
def raise_salary(self, rate):
"""연봉 인상"""
self.salary = int(self.salary * (1 + rate / 100))
print(f"💰 연봉이 {rate}% 인상되었습니다!")
def print_info(self):
"""직원 정보 출력"""
print("=" * 40)
print(f"이름: {self.name}")
print(f"부서: {self.department}")
print(f"연봉: {self.salary:,}원")
print("=" * 40)
@classmethod
def get_employee_count(cls):
"""총 직원 수 반환"""
return cls.employee_count
# 테스트
emp1 = Employee("홍길동", "개발팀", 50000000)
emp2 = Employee("김철수", "디자인팀", 45000000)
print()
emp1.print_info()
emp1.raise_salary(10)
emp1.print_info()
print(f"\n총 직원 수: {Employee.get_employee_count()}명")
|
문제 2: 도서 대여 시스템
다음 요구사항을 만족하는 Library 클래스를 작성하세요:
요구사항:
- 생성자로 도서관 이름 초기화, 도서 목록은 빈 리스트
- 도서 추가 메서드
- 도서 대여 메서드 (대여 가능 여부 체크)
- 도서 반납 메서드
- 전체 도서 목록 출력 메서드
1
2
3
4
5
6
7
8
9
10
| # 사용 예시
library = Library("파이썬 도서관")
library.add_book("파이썬 정복", "홍길동")
library.add_book("자료구조", "김철수")
library.print_books()
library.borrow_book("파이썬 정복")
library.print_books()
library.return_book("파이썬 정복")
library.print_books()
|
💡 힌트
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| class Library:
def __init__(self, name):
self.name = name
self.books = [] # [{"title": "...", "author": "...", "available": True}, ...]
def add_book(self, title, author):
# 도서 추가 (기본값 available=True)
pass
def borrow_book(self, title):
# 도서 찾기
# available이 True면 False로 변경
pass
def return_book(self, title):
# 도서 찾기
# available을 True로 변경
pass
def print_books(self):
# 도서 목록 출력
pass
|
✅ 정답
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
| class Library:
"""도서관을 관리하는 클래스"""
def __init__(self, name):
"""생성자: 도서관 초기화"""
print(f"📚 '{name}' 도서관이 개관했습니다!\n")
self.name = name
self.books = []
def add_book(self, title, author):
"""도서 추가"""
self.books.append({
"title": title,
"author": author,
"available": True
})
print(f"✅ '{title}' 도서가 추가되었습니다.")
def borrow_book(self, title):
"""도서 대여"""
for book in self.books:
if book["title"] == title:
if book["available"]:
book["available"] = False
print(f"📖 '{title}' 도서를 대여했습니다.")
return
else:
print(f"❌ '{title}' 도서는 이미 대여 중입니다.")
return
print(f"❌ '{title}' 도서를 찾을 수 없습니다.")
def return_book(self, title):
"""도서 반납"""
for book in self.books:
if book["title"] == title:
if not book["available"]:
book["available"] = True
print(f"✅ '{title}' 도서를 반납했습니다.")
return
else:
print(f"❌ '{title}' 도서는 대여 중이 아닙니다.")
return
print(f"❌ '{title}' 도서를 찾을 수 없습니다.")
def print_books(self):
"""도서 목록 출력"""
print(f"\n{'='*50}")
print(f"{self.name} - 도서 목록")
print(f"{'='*50}")
if not self.books:
print("등록된 도서가 없습니다.")
else:
for i, book in enumerate(self.books, 1):
status = "✅ 대여 가능" if book["available"] else "❌ 대여 중"
print(f"{i}. {book['title']} ({book['author']}) - {status}")
print(f"{'='*50}\n")
# 테스트
library = Library("파이썬 도서관")
library.add_book("파이썬 정복", "홍길동")
library.add_book("자료구조", "김철수")
library.add_book("알고리즘", "이영희")
library.print_books()
library.borrow_book("파이썬 정복")
library.borrow_book("파이썬 정복") # 이미 대여 중
library.print_books()
library.return_book("파이썬 정복")
library.print_books()
|
📝 오늘 배운 내용 정리
| 개념 | 설명 | 예시 |
__init__ | 생성자, 객체 초기화 | def __init__(self, name): |
__del__ | 소멸자, 객체 정리 | def __del__(self): |
| 기본값 매개변수 | 생성자 매개변수 기본값 | def __init__(self, name, age=0): |
| 자동 호출 | 생성/소멸 시 자동 실행 | 명시적 호출 불필요 |
생성자와 소멸자 비교
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| class Example:
def __init__(self, name):
"""생성자: 객체 생성 시 자동 호출"""
self.name = name
print(f"✨ {name} 생성")
def __del__(self):
"""소멸자: 객체 삭제 시 자동 호출"""
print(f"💀 {self.name} 소멸")
# 생성자 자동 호출
obj = Example("테스트") # ✨ 테스트 생성
# 소멸자 자동 호출
del obj # 💀 테스트 소멸
|
베스트 프랙티스
✅ 생성자 사용:
- 객체 생성 시 필수 데이터 초기화
- 기본값 제공으로 유연성 확보
- 초기화 로직을 생성자에 집중
✅ 소멸자 사용:
- 리소스 정리가 필요한 경우에만 사용
- 가능하면 명시적 정리 메서드 제공 (
close(), cleanup() 등) - Context Manager(
with 문) 사용 권장
❌ 피해야 할 패턴:
- 생성자에서 복잡한 로직 수행
- 소멸자에 의존적인 리소스 관리
- 생성자에서 예외 발생 가능한 작업
🔗 관련 자료
📚 이전 학습
Day 31: 클래스와 객체 ⭐⭐⭐
어제는 객체지향 프로그래밍의 기초인 클래스와 객체의 개념을 배웠습니다!
📚 다음 학습
Day 33: 인스턴스 메서드 ⭐⭐⭐
내일은 인스턴스 메서드를 심화적으로 배우고 메서드를 활용하는 방법을 익힙니다!
“늦었다고 생각할 때가 가장 빠른 시기입니다!” 🚀
| Day 32/100 | Phase 4: 객체지향 프로그래밍 | #100DaysOfPython |