
26. 클래스와 객체 (1) - 나만의 자료형 만들기
리스트, 딕셔너리, 문자열... 지금까지 써온 것들은 모두 객체다. 이번에는 나만의 자료형을 만드는 방법, 바로 클래스(Class)를 배워보자. 객체지향 프로그래밍(OOP)의 첫걸음이다.
클래스란? - 붕어빵틀 비유
클래스를 이해하는 가장 쉬운 비유는 붕어빵틀과 붕어빵이다.
- 클래스(Class) = 붕어빵틀 (설계도)
- 인스턴스(Instance) = 붕어빵 (실제 만들어진 것)
- 속성(Attribute) = 속재료 (팥, 슈크림, 피자...)
- 메서드(Method) = 굽기, 포장하기 (할 수 있는 동작)
하나의 틀(클래스)로 여러 개의 붕어빵(인스턴스)을 만들 수 있고, 각 붕어빵은 서로 다른 속재료를 가질 수 있다.

첫 번째 클래스 만들기
class Dog:
pass
# 인스턴스 생성
my_dog = Dog()
your_dog = Dog()
print(type(my_dog)) # <class '__main__.Dog'>
print(my_dog == your_dog) # False — 서로 다른 인스턴스!
class 키워드로 정의하고, 클래스 이름은 대문자로 시작한다(PascalCase).
init - 초기화 메서드
__init__은 인스턴스가 생성될 때 자동으로 호출되는 메서드다. 속성(데이터)을 초기화하는 역할을 한다.
class Dog:
def __init__(self, name, breed, age):
self.name = name # 이름
self.breed = breed # 품종
self.age = age # 나이
# 인스턴스 생성
dog1 = Dog("멍멍이", "골든리트리버", 3)
dog2 = Dog("초코", "푸들", 5)
print(f"{dog1.name}은 {dog1.breed}, {dog1.age}살")
# 멍멍이은 골든리트리버, 3살
print(f"{dog2.name}은 {dog2.breed}, {dog2.age}살")
# 초코은 푸들, 5살
self란?
self는 인스턴스 자기 자신을 가리킨다.
class Dog:
def __init__(self, name, age):
self.name = name # self.name: 인스턴스의 속성
self.age = age # name: 매개변수
self.name = name: 매개변수name의 값을 인스턴스의 속성self.name에 저장- 메서드를 호출할 때
self는 자동으로 전달된다. 직접 넣지 않는다.
dog1 = Dog("멍멍이", 3)
# 파이썬이 내부적으로 Dog.__init__(dog1, "멍멍이", 3) 으로 호출
메서드 (Method) - 객체의 동작
메서드는 클래스 안에 정의된 함수다. 첫 번째 매개변수는 항상 self이다.
class Dog:
def __init__(self, name, breed, age):
self.name = name
self.breed = breed
self.age = age
def bark(self):
print(f"{self.name}: 멍멍!")
def info(self):
print(f"이름: {self.name}, 품종: {self.breed}, 나이: {self.age}살")
def birthday(self):
self.age += 1
print(f"{self.name}이(가) {self.age}살이 되었습니다!")
# 사용
dog = Dog("멍멍이", "골든리트리버", 3)
dog.bark() # 멍멍이: 멍멍!
dog.info() # 이름: 멍멍이, 품종: 골든리트리버, 나이: 3살
dog.birthday() # 멍멍이이(가) 4살이 되었습니다!
dog.info() # 이름: 멍멍이, 품종: 골든리트리버, 나이: 4살
클래스 변수 vs 인스턴스 변수
인스턴스 변수
self.변수명으로 정의. 각 인스턴스마다 독립적이다.
class Student:
def __init__(self, name, score):
self.name = name # 인스턴스 변수
self.score = score # 인스턴스 변수
s1 = Student("김철수", 85)
s2 = Student("이영희", 92)
print(s1.name, s1.score) # 김철수 85
print(s2.name, s2.score) # 이영희 92
클래스 변수
클래스 본문에 직접 정의. 모든 인스턴스가 공유한다.
class Student:
school = "파이썬고등학교" # 클래스 변수 (모든 인스턴스가 공유)
count = 0 # 클래스 변수
def __init__(self, name, score):
self.name = name # 인스턴스 변수
self.score = score # 인스턴스 변수
Student.count += 1 # 클래스 변수 수정
s1 = Student("김철수", 85)
s2 = Student("이영희", 92)
s3 = Student("박민수", 78)
print(f"학교: {Student.school}") # 파이썬고등학교
print(f"학생 수: {Student.count}") # 3
# 인스턴스에서도 접근 가능 (읽기)
print(f"{s1.name}의 학교: {s1.school}") # 파이썬고등학교
차이점 정리
class Example:
class_var = "클래스 변수" # 모든 인스턴스가 공유
def __init__(self):
self.instance_var = "인스턴스 변수" # 각자 독립
a = Example()
b = Example()
# 클래스 변수 — 공유
print(a.class_var) # 클래스 변수
print(b.class_var) # 클래스 변수
# 인스턴스 변수 — 독립
a.instance_var = "A의 값"
print(a.instance_var) # A의 값
print(b.instance_var) # 인스턴스 변수 (영향 없음)
주의: 인스턴스에서 클래스 변수와 같은 이름으로 대입하면, 인스턴스 변수가 새로 생성되어 클래스 변수를 가린다.
실전 예시: 은행 계좌 클래스
class BankAccount:
interest_rate = 0.02 # 클래스 변수: 연 이자율 2%
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
def deposit(self, amount):
"""입금"""
if amount > 0:
self.balance += amount
print(f"[입금] {amount:,}원 → 잔액: {self.balance:,}원")
else:
print("입금액은 0보다 커야 합니다.")
def withdraw(self, amount):
"""출금"""
if amount > self.balance:
print(f"잔액 부족! (잔액: {self.balance:,}원)")
elif amount <= 0:
print("출금액은 0보다 커야 합니다.")
else:
self.balance -= amount
print(f"[출금] {amount:,}원 → 잔액: {self.balance:,}원")
def apply_interest(self):
"""이자 적용"""
interest = int(self.balance * BankAccount.interest_rate)
self.balance += interest
print(f"[이자] {interest:,}원 적용 → 잔액: {self.balance:,}원")
def info(self):
"""계좌 정보"""
print(f"예금주: {self.owner}, 잔액: {self.balance:,}원")
# 사용
acc = BankAccount("김철수")
acc.deposit(1000000) # [입금] 1,000,000원 → 잔액: 1,000,000원
acc.deposit(500000) # [입금] 500,000원 → 잔액: 1,500,000원
acc.withdraw(200000) # [출금] 200,000원 → 잔액: 1,300,000원
acc.apply_interest() # [이자] 26,000원 적용 → 잔액: 1,326,000원
acc.info() # 예금주: 김철수, 잔액: 1,326,000원
실전 예시: 학생 성적 관리
class Student:
def __init__(self, name, student_id):
self.name = name
self.student_id = student_id
self.scores = {} # 과목별 점수
def add_score(self, subject, score):
"""과목 점수 추가"""
self.scores[subject] = score
def get_average(self):
"""평균 계산"""
if not self.scores:
return 0
return sum(self.scores.values()) / len(self.scores)
def get_grade(self):
"""학점 산출"""
avg = self.get_average()
if avg >= 90: return "A"
elif avg >= 80: return "B"
elif avg >= 70: return "C"
elif avg >= 60: return "D"
else: return "F"
def report(self):
"""성적표 출력"""
print(f"\n{'='*30}")
print(f" {self.name} ({self.student_id})")
print(f"{'='*30}")
for subject, score in self.scores.items():
print(f" {subject}: {score}점")
print(f"{'-'*30}")
print(f" 평균: {self.get_average():.1f}점 ({self.get_grade()})")
# 사용
s = Student("김철수", "2025001")
s.add_score("국어", 85)
s.add_score("영어", 92)
s.add_score("수학", 78)
s.report()
출력:
==============================
김철수 (2025001)
==============================
국어: 85점
영어: 92점
수학: 78점
------------------------------
평균: 85.0점 (B)
직접 해보기
문제 1. Rectangle 클래스를 만들어보자. 가로(width)와 세로(height)를 속성으로 가지고, area() (넓이)와 perimeter() (둘레) 메서드를 구현하자.
문제 2. Counter 클래스를 만들어보자. increment(), decrement(), reset(), get_value() 메서드를 구현하자. 초기값은 0이다.
문제 3. Book 클래스를 만들어보자. 제목, 저자, 가격 속성과 discount(percent) 메서드(할인 적용), info() 메서드를 구현하자. 클래스 변수로 total_books (총 책 수)를 관리하자.
문제 4. TodoList 클래스를 만들어보자. add(task), done(index), show() 메서드를 구현하자. 각 할 일은 완료 여부를 가진다.
정답 보기
# 문제 1 - Rectangle
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
r = Rectangle(5, 3)
print(f"넓이: {r.area()}") # 15
print(f"둘레: {r.perimeter()}") # 16
# 문제 2 - Counter
class Counter:
def __init__(self):
self.value = 0
def increment(self):
self.value += 1
def decrement(self):
self.value -= 1
def reset(self):
self.value = 0
def get_value(self):
return self.value
c = Counter()
c.increment()
c.increment()
c.increment()
c.decrement()
print(c.get_value()) # 2
c.reset()
print(c.get_value()) # 0
# 문제 3 - Book
class Book:
total_books = 0
def __init__(self, title, author, price):
self.title = title
self.author = author
self.price = price
Book.total_books += 1
def discount(self, percent):
self.price = int(self.price * (1 - percent / 100))
print(f"할인 적용! 새 가격: {self.price:,}원")
def info(self):
print(f"'{self.title}' by {self.author} - {self.price:,}원")
b1 = Book("파이썬 입문", "김파이", 25000)
b2 = Book("자료구조", "이코딩", 30000)
b1.info() # '파이썬 입문' by 김파이 - 25,000원
b1.discount(20) # 할인 적용! 새 가격: 20,000원
print(f"총 책 수: {Book.total_books}") # 2
# 문제 4 - TodoList
class TodoList:
def __init__(self):
self.tasks = []
def add(self, task):
self.tasks.append({"task": task, "done": False})
print(f"추가: {task}")
def done(self, index):
if 0 <= index < len(self.tasks):
self.tasks[index]["done"] = True
print(f"완료: {self.tasks[index]['task']}")
else:
print("잘못된 번호입니다.")
def show(self):
print("\n=== 할 일 목록 ===")
for i, t in enumerate(self.tasks):
status = "V" if t["done"] else " "
print(f" [{status}] {i}. {t['task']}")
todo = TodoList()
todo.add("파이썬 공부")
todo.add("운동하기")
todo.add("장보기")
todo.done(0)
todo.show()
오늘의 정리
| 항목 | 내용 |
|---|---|
| 클래스 | 객체의 설계도. class 이름:으로 정의 |
| 인스턴스 | 클래스로부터 만들어진 실제 객체. 이름()으로 생성 |
| __init__ | 초기화 메서드. 인스턴스 생성 시 자동 호출 |
| self | 인스턴스 자기 자신을 가리킴. 메서드의 첫 매개변수 |
| 인스턴스 변수 | self.변수 — 각 인스턴스마다 독립 |
| 클래스 변수 | 클래스 본문에 정의 — 모든 인스턴스가 공유 |
다음 편 예고: 클래스와 객체 (2) - 상속과 다형성
기존 클래스를 확장해서 새 클래스를 만드는 상속, 같은 메서드가 다르게 동작하는 다형성을 알아보자!
태그: 파이썬 Python 파이썬독학 클래스 class 객체 OOP init 인스턴스 파이썬중급 IT교육
'Python' 카테고리의 다른 글
| 28. 매직 메서드 - 파이썬 객체의 비밀 (0) | 2026.02.23 |
|---|---|
| 27. 클래스와 객체 (2) - 상속과 다형성 (0) | 2026.02.22 |
| 25. 가상환경과 프로젝트 관리 - 프로처럼 세팅하기 (1) | 2026.02.22 |
| 24. 정규표현식 - 문자열 처리의 끝판왕 (0) | 2026.02.22 |
| 23. 파일 읽기/쓰기 - 데이터를 저장하자 (0) | 2026.02.22 |
댓글