파이썬 객체지향 프로그래밍 실전 예제 20개
클래스, 객체, 생성자, 상속, 다형성, 캡슐화까지 한 번에 정리하는 학교 제출용 HTML 자료
학습 포인트
class, self, __init__의 기본 구조 이해
- 인스턴스 변수 / 클래스 변수 / 클래스 메서드 / 정적 메서드 구분
- 상속, 오버라이딩,
super(), 다형성 이해
- 학생 관리, 계좌, 쇼핑카트, 게임 캐릭터 같은 실전형 예제 적용
기초
1. 클래스와 객체 만들기
핵심 개념: 클래스를 정의하고 객체를 생성하는 가장 기본적인 형태입니다.
예시 코드
class Dog:
pass
d = Dog()
print(type(d))
예상 결과:
<class '__main__.Dog'>
설명: Dog는 설계도이고, d는 그 설계도로 만든 객체(인스턴스)입니다.
기초
2. 생성자 __init__ 사용
핵심 개념: 객체가 만들어질 때 자동으로 속성을 초기화합니다.
예시 코드
class Student:
def __init__(self, name, grade):
self.name = name
self.grade = grade
s = Student("민수", 2)
print(s.name, s.grade)
예상 결과:
민수 2
설명: __init__은 객체 생성 직후 자동 실행되며, self.name처럼 인스턴스 속성을 저장합니다.
기초
3. 인스턴스 메서드 만들기
핵심 개념: 객체에 동작을 부여하는 메서드를 정의합니다.
예시 코드
class Calculator:
def add(self, a, b):
return a + b
c = Calculator()
print(c.add(3, 5))
예상 결과:
8
설명: 메서드는 반드시 첫 번째 매개변수로 self를 받아 현재 객체 자신을 가리킵니다.
기초
4. 객체 상태 출력하기
핵심 개념: __str__을 사용하면 객체를 print할 때 보기 좋은 문자열을 반환할 수 있습니다.
예시 코드
class Book:
def __init__(self, title):
self.title = title
def __str__(self):
return f"책 제목: {self.title}"
b = Book("파이썬 입문")
print(b)
예상 결과:
책 제목: 파이썬 입문
설명: __str__은 객체를 문자열처럼 표현할 때 자동 호출됩니다.
속성
5. 클래스 변수 사용
핵심 개념: 모든 객체가 공유하는 값을 클래스 변수로 만들 수 있습니다.
예시 코드
class Counter:
count = 0
def __init__(self):
Counter.count += 1
a = Counter()
b = Counter()
print(Counter.count)
예상 결과:
2
설명: count는 클래스 전체가 공유하는 값이며, 객체마다 따로 생기지 않습니다.
속성
6. 인스턴스 변수와 클래스 변수 차이
핵심 개념: 공유 변수와 개별 변수를 함께 비교해 봅니다.
예시 코드
class Person:
species = "human"
def __init__(self, name):
self.name = name
p1 = Person("철수")
p2 = Person("영희")
print(p1.species, p2.species)
print(p1.name, p2.name)
예상 결과:
human human
철수 영희
설명: species는 공유되고, name은 각 객체마다 따로 저장됩니다.
메서드
7. 클래스 메서드 @classmethod
핵심 개념: 클래스 자체를 다루는 메서드를 만들 수 있습니다.
예시 코드
class School:
total = 0
@classmethod
def add_student(cls):
cls.total += 1
School.add_student()
School.add_student()
print(School.total)
예상 결과:
2
설명: cls는 클래스 자신을 가리키며, 클래스 수준 데이터를 수정할 때 유용합니다.
메서드
8. 정적 메서드 @staticmethod
핵심 개념: 객체나 클래스 정보 없이 독립적으로 동작하는 함수를 클래스 안에 둘 수 있습니다.
예시 코드
class MathTool:
@staticmethod
def square(x):
return x * x
print(MathTool.square(6))
예상 결과:
36
설명: 정적 메서드는 self나 cls를 받지 않으며, 기능상 관련된 함수를 묶을 때 좋습니다.
캡슐화
9. 비공개 속성 흉내내기
핵심 개념: 언더스코어 두 개를 사용해 직접 접근을 어렵게 만들 수 있습니다.
예시 코드
class Account:
def __init__(self, money):
self.__money = money
def show(self):
return self.__money
a = Account(5000)
print(a.show())
예상 결과:
5000
설명: __money는 이름 변경(name mangling)이 적용되어 외부 직접 접근을 어렵게 합니다.
캡슐화
10. getter / setter 스타일
핵심 개념: 메서드를 통해 값을 안전하게 읽고 수정합니다.
예시 코드
class Temperature:
def __init__(self):
self._c = 0
def set_c(self, value):
if value >= -273:
self._c = value
def get_c(self):
return self._c
t = Temperature()
t.set_c(25)
print(t.get_c())
예상 결과:
25
설명: setter에서 조건 검사를 넣어 잘못된 값이 들어가지 않게 할 수 있습니다.
프로퍼티
11. @property 사용
핵심 개념: 메서드를 속성처럼 접근할 수 있게 만듭니다.
예시 코드
class Circle:
def __init__(self, r):
self.r = r
@property
def area(self):
return 3.14 * self.r ** 2
c = Circle(3)
print(c.area)
예상 결과:
28.26
설명: area()처럼 호출하지 않고 c.area처럼 속성처럼 읽을 수 있습니다.
상속
12. 상속의 기본
핵심 개념: 기존 클래스를 물려받아 새로운 클래스를 만들 수 있습니다.
예시 코드
class Animal:
def speak(self):
return "소리를 낸다"
class Cat(Animal):
pass
c = Cat()
print(c.speak())
예상 결과:
소리를 낸다
설명: Cat은 Animal의 메서드를 그대로 물려받습니다.
상속
13. 메서드 오버라이딩
핵심 개념: 상속받은 메서드를 자식 클래스에서 새롭게 정의할 수 있습니다.
예시 코드
class Animal:
def speak(self):
return "..."
class Cat(Animal):
def speak(self):
return "야옹"
print(Cat().speak())
예상 결과:
야옹
설명: 같은 이름의 메서드를 다시 정의하면 자식 클래스의 버전이 우선 사용됩니다.
상속
14. super()로 부모 생성자 호출
핵심 개념: 부모 클래스의 초기화 코드를 재사용할 수 있습니다.
예시 코드
class Person:
def __init__(self, name):
self.name = name
class Teacher(Person):
def __init__(self, name, subject):
super().__init__(name)
self.subject = subject
t = Teacher("김선생", "수학")
print(t.name, t.subject)
예상 결과:
김선생 수학
설명: super().__init__()을 쓰면 부모 클래스의 초기화 로직을 그대로 활용할 수 있습니다.
다형성
15. 같은 메서드 이름, 다른 동작
핵심 개념: 서로 다른 객체가 같은 메서드 이름에 대해 다르게 반응할 수 있습니다.
예시 코드
class Dog:
def speak(self):
return "멍멍"
class Cat:
def speak(self):
return "야옹"
for animal in [Dog(), Cat()]:
print(animal.speak())
예상 결과:
멍멍
야옹
설명: 둘 다 speak()를 가지고 있으므로, 같은 코드로 서로 다른 객체를 처리할 수 있습니다.
실전
16. 학생 성적 관리 클래스
핵심 개념: 리스트 속성을 가진 객체를 만들어 평균을 계산합니다.
예시 코드
class Student:
def __init__(self, name):
self.name = name
self.scores = []
def add_score(self, score):
self.scores.append(score)
def average(self):
return sum(self.scores) / len(self.scores)
s = Student("지수")
s.add_score(90)
s.add_score(100)
print(s.average())
예상 결과:
95.0
설명: 객체 안에 리스트를 두면 관련 데이터를 하나로 묶어 관리하기 좋습니다.
실전
17. 은행 계좌 입출금
핵심 개념: 상태 변화가 있는 객체를 만들어 입금과 출금을 처리합니다.
예시 코드
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
def deposit(self, money):
self.balance += money
def withdraw(self, money):
if money <= self.balance:
self.balance -= money
a = BankAccount("민호", 10000)
a.deposit(5000)
a.withdraw(3000)
print(a.balance)
예상 결과:
12000
설명: 객체는 현재 상태(balance)를 저장하고, 메서드로 그 상태를 변경합니다.
실전
18. 쇼핑카트 클래스
핵심 개념: 상품 목록을 담고 총합을 계산하는 객체를 만듭니다.
예시 코드
class Cart:
def __init__(self):
self.items = []
def add(self, name, price):
self.items.append((name, price))
def total(self):
return sum(price for _, price in self.items)
c = Cart()
c.add("노트", 2000)
c.add("펜", 1000)
print(c.total())
예상 결과:
3000
설명: 관련 데이터를 묶고 총합 계산 기능까지 제공하면 재사용성이 높은 객체가 됩니다.
실전
19. 게임 캐릭터 상속 구조
핵심 개념: 기본 캐릭터를 만들고 전사/마법사로 확장할 수 있습니다.
예시 코드
class Character:
def __init__(self, name, hp):
self.name = name
self.hp = hp
class Warrior(Character):
def attack(self):
return "검 공격!"
class Wizard(Character):
def attack(self):
return "마법 공격!"
print(Warrior("아더", 100).attack())
print(Wizard("메린", 80).attack())
예상 결과:
검 공격!
마법 공격!
설명: 공통 속성(name, hp)은 부모에 두고, 직업별 행동은 자식에서 나눌 수 있습니다.
실전
20. 연산자 오버로딩 __add__
핵심 개념: 객체끼리 + 연산을 가능하게 할 수 있습니다.
예시 코드
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Point(self.x + other.x, self.y + other.y)
def __str__(self):
return f"({self.x}, {self.y})"
p1 = Point(1, 2)
p2 = Point(3, 4)
print(p1 + p2)
예상 결과:
(4, 6)
설명: __add__를 정의하면 객체끼리 덧셈 연산의 의미를 직접 설계할 수 있습니다.