본문 바로가기
python

파이썬 기초 - 클래스 기초

by kyeongseo.oh 2025. 3. 16.

클래스의 개념과 객체 생성

클래스란?

클래스는 객체를 만들기 위한 '설계도'다. 실제 사물이나 개념을 프로그래밍으로 표현하기 위한 틀이라고 할 수 있다.

예를 들어, 집을 지을 때 설계도가 필요한 것처럼 프로그래밍에서도 객체를 만들기 전에 그 객체가 어떤 속성을 가지고 어떤 기능을 하는지 정의해야 한다. 이러한 정의를 담고 있는 것이 바로 클래스다.

# 강아지 클래스(설계도) 정의
class Dog:
    # 초기화 메서드: 객체가 생성될 때 자동으로 호출됨
    def __init__(self, name, weight):
        self.name = name  # 강아지 이름 속성
        self.weight = weight    # 강아지 무게 속성
    
    # 강아지의 행동을 나타내는 메서드
    def bark(self):
        return f"{self.name}가 멍멍! 짖는다."
    
    def eat(self):
        self.weight += 1
        return f"{self.name}은 밥을 먹었다. 이제 {self.weight}kg이 되었다."

객체란?

객체는 클래스를 바탕으로 실제로 생성된 실체다. 같은 클래스로 여러 객체를 만들 수 있으며, 각 객체는 서로 독립적이다.

예를 들어, 같은 설계도(클래스)로 여러 채의 집을 지을 수 있는 것처럼, 하나의 클래스로 여러 객체를 생성할 수 있다.

# Dog 클래스(설계도)로 실제 강아지 객체 생성
maltese = Dog("댕댕일", 3)    # 댕댕일이라는 이름의 3kg 강아지 객체
poodle = Dog("댕댕이", 5)     # 댕댕이라는 이름의 5kg 강아지 객체

# 강아지 객체 사용하기
print(maltese.name)       # 댕댕일
print(poodle.weight)      # 5
print(maltese.bark())     # 댕댕일(이)가 와르르왈! 짖는다.
print(poodle.eat())       # 댕댕이(는)은 밥을 먹었다. 이제 6kg이 되었다.
print(poodle.eat())       # 댕댕이(는)은 밥을 먹었다. 이제 7kg이 되었다.
print(poodle.eat())       # 댕댕이(는)은 밥을 먹었다. 이제 8kg이 되었다.

그림으로 이해하는 클래스와 객체

[클래스(설계도): Dog]
+---------------------+
| 속성:               |
|  - name (이름)      |
|  - weight (나이)       |
|                     |
| 메서드:             |
|  - bark()           |
|  - eat()            |
|                     |
+---------------------+
        |
        ↓ 객체 생성
    +-------+   +-------+
    | 댕댕일 |  | 댕댕이 |
    +-------+   +-------+
  | name:댕댕일 | name: 댕댕이|
  | weight: 3   | weight: 5  |
    +-------+   +-------

상속과 다형성

상속이란?

상속은 기존 클래스의 속성과 메서드를 새로운 클래스가 물려받는 것이다. 이를 통해 코드 재사용성을 높이고 관계를 표현할 수 있다.

예를 들어, 모든 동물이 가진 공통 특성을 정의한 클래스가 있고, 그것을 바탕으로 강아지나 새 같은 특정 동물의 클래스를 만들 수 있다.

# 동물(부모) 클래스
class Animal:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def eat(self):
        return f"{self.name}이(가) 먹이를 먹는다."
    
    def sleep(self):
        return f"{self.name}이(가) 잠을 잔다."

# 강아지(자식) 클래스 - Animal을 상속받음
class Dog(Animal):
    # 추가 특성
    def __init__(self, name, age, breed):
        # 부모 클래스의 초기화 메서드 호출
        super().__init__(name, age)
        self.breed = breed  # 강아지 품종
    
    # 강아지만의 특별한 메서드
    def bark(self):
        return f"{self.name}이(가) 멍멍! 짖는다."
    
    def wait(self):
        return f"{self.name}이(가) 기다린다."

# 새(자식) 클래스 - Animal을 상속받음
class Bird(Animal):
    def fly(self):
        return f"{self.name}이(가) 퍼드득 날아오른다."
    

# 객체 생성 및 사용
dog = Dog("댕댕삼", 3, "진돗개")
bird = Bird("앵무", 2)

# 부모 클래스(Animal)의 메서드 사용
print(dog.eat())    # 출력: 댕댕삼이(가) 먹이를 먹는다.
print(bird.sleep())  # 출력: 앵무이(가) 잠을 잔다.

# 각자의 특별한 메서드 사용
print(dog.bark())     # 출력: 댕댕삼이(가) 멍멍! 짖는다.
print(bird.fly())     # 출력: 앵무이(가) 퍼드득 날아오른다.

# 강아지만의 추가 속성
print(dog.breed)      # 출력: 진돗개

그림으로 이해하는 상속

     [Animal]
     +---------------+
     | - name        |
     | - age         |
     |               |
     | + eat()       |
     | + sleep()     |
     +-------+-------+
             ^
             |
     +-------+-------+
     |               |
[Dog]                 [Bird]
+---------------+    +---------------+
| - breed       |    |               |
|               |    |               |
| + bark()      |    | + fly()       |
| + wait()      |    |               |
+---------------+    +---------------+

Method Overriding?

메소드 오버라이딩은 부모 클래스에서 정의된 메소드를 자식 클래스에서 재정의하는 기법이다.

예를 들어, '소리 내기'라는 동일한 메소드를 동물마다 다르게 재정의 할 수 있다. ex)강아지는 '멍멍', 고양이는 '야옹', 오리는 '꽥꽥'

# 동물 클래스
class Animal:
    def __init__(self, name):
        self.name = name
    
    def make_sound(self):
        return "울부짖는다."

# 강아지 클래스
class Dog(Animal):
    def make_sound(self):
        return "멍멍!"

# 고양이 클래스
class Cat(Animal):
    def make_sound(self):
        return "야옹!"

# 오리 클래스
class Duck(Animal):
    def make_sound(self):
        return "꽥꽥!"

class Human(Animal):
   pass

# 동물들의 소리 출력 함수
def animal_sounds(animals):
    for animal in animals:
        print(f"{animal.name}: {animal.make_sound()}")

# 여러 동물 객체 생성
dog = Dog("바둑이")
cat = Cat("나비")
duck = Duck("오리")
human = Human("사람")

# 모든 동물의 소리 출력
animals = [dog, cat, duck, human]
animal_sounds(animals)
# 출력:
# 바둑이: 멍멍!
# 나비: 야옹!
# 오리: 꽥꽥!
# 사람: 울부짖는다.

super() 함수와 메서드 호출

super() 함수는 부모 클래스의 메서드를 호출할 때 사용된다. 이를 통해 자식 클래스에서 부모 클래스의 기능을 확장하거나 수정할 수 있다.

class Vehicle:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
    
    def start_engine(self):
        return "엔진 시동!"
    
    def info(self):
        return f"{self.year} {self.make} {self.model}"

class ElectricCar(Vehicle):
    def __init__(self, make, model, year, battery_capacity):
        # 부모 클래스의 __init__ 메서드 호출
        super().__init__(make, model, year)
        self.battery_capacity = battery_capacity
    
    # 메서드 오버라이딩 + 부모 메서드 확장
    def start_engine(self):
        # 부모 클래스의 start_engine 메서드 호출 후 추가 기능 구현
        parent_result = super().start_engine()
        return f"{parent_result} (전기 모터 작동 중...)"
    
    # 부모 메서드 활용 + 확장
    def info(self):
        # 부모 클래스의 info 메서드 호출 후 추가 정보 포함
        basic_info = super().info()
        return f"{basic_info} - 배터리: {self.battery_capacity}kWh"

# 객체 생성
tesla = ElectricCar("Tesla", "Model 3", 2023, 75)

# 메서드 호출
print(tesla.start_engine())  # 출력: 엔진 시동! (전기 모터 작동 중...)
print(tesla.info())  # 출력: 2023 Tesla Model 3 - 배터리: 75kWh

예제: 게임 캐릭터 시스템

기본 요구사항

1. 기본 캐릭터 클래스 구현

  • Character 클래스를 구현한다.
  • 속성:
    • name: 캐릭터 이름
    • health: 체력(HP)
    • power: 공격력
  • 메소드:
    • __init__(self, name, health, power): 초기화 메소드
    • attack(self): 기본 공격 수행 (메시지 반환)
    • take_damage(self, damage): 피해를 입는 메소드 (체력 감소 및 메시지 반환)

2. 전사(Warrior) 클래스 구현

  • Character 클래스를 상속받아 구현한다.
  • 추가 속성:
    • armor: 방어력
  • 메소드:
    • __init__(self, name, health, power, armor): 초기화 메소드 (부모 클래스의 초기화 메소드 호출)
    • take_damage(self, damage): 메소드 오버라이딩 - 방어력을 고려한 피해 계산 (부모 클래스의 메소드 호출)
    • heavy_attack(self): 전사만의 특수 공격 기능 (공격력의 2배 데미지)

3. 마법사(Wizard) 클래스 구현

  • Character 클래스를 상속받아 구현하세요.
  • 추가 속성:
    • mana: 마나
  • 메소드:
    • __init__(self, name, health, power, mana): 초기화 메소드 (부모 클래스의 초기화 메소드 호출)
    • fireball(self): 파이어볼 마법 (마나 20 소모, 공격력의 3배 데미지)
    • heal(self): 치유 마법 (마나 10 소모, 체력 20 회복)

4. 게임 시뮬레이션

  • 각 클래스의 객체를 생성하여 다음 동작을 시뮬레이션한다.
    • 전사와 마법사의 기본 공격
    • 전사의 특수 공격(heavy_attack)
    • 마법사의 특수 공격(fireball)
    • 전사와 마법사가 피해를 입는 상황
    • 마법사의 치유 마법 사용
# 기본 캐릭터 클래스
class Character:
    def __init__(self, name, health, power):
        self.name = name      # 캐릭터 이름
        self.health = health  # 체력
        self.power = power    # 공격력
    
    def attack(self):
        return f"{self.name}이(가) {self.power}의 공격력으로 공격한다."
    
    def take_damage(self, damage):
        self.health -= damage
        if self.health <= 0:
            return f"{self.name}이(가) 쓰러졌다."
        return f"{self.name}이(가) {damage}의 피해를 입었다. 남은 체력: {self.health}"

# 전사 클래스 (Character 상속)
class Warrior(Character):
    def __init__(self, name, health, power, armor):
        super().__init__(name, health, power)
        self.armor = armor  # 방어력
    
    # 메서드 오버라이딩
    def take_damage(self, damage):
        # 방어력 적용하여 피해 감소
        actual_damage = max(1, damage - self.armor)
        return super().take_damage(actual_damage)
    
    # 전사만의 특별한 능력
    def heavy_attack(self):
        return f"{self.name}이(가) {self.power * 2}의 강력한 공격을 한다. (체력 -10)"

# 마법사 클래스 (Character 상속)
class Wizard(Character):
    def __init__(self, name, health, power, mana):
        super().__init__(name, health, power)
        self.mana = mana  # 마나
    
    # 마법사만의 특별한 능력
    def fireball(self):
        if self.mana >= 20:
            self.mana -= 20
            return f"{self.name}이(가) 파이어볼을 사용했다. 적에게 {self.power * 3}의 피해를 입힌다. 남은 마나: {self.mana}"
        else:
            return f"{self.name}의 마나가 부족하다."
    
    def heal(self):
        if self.mana >= 10:
            self.mana -= 10
            self.health += 20
            return f"{self.name}이(가) 치유 마법을 사용했다. 체력이 20 회복되었다. 현재 체력: {self.health}, 남은 마나: {self.mana}"
        else:
            return f"{self.name}의 마나가 부족하다."

# 게임 캐릭터 객체 생성
warrior = Warrior(name="강철의 기사", health=100, power=15, armor=5)
wizard = Wizard(name="현명한 마법사", health=70, power=10, mana=100)

# 게임 플레이 시뮬레이션
print("=== 게임 시작 ===")
print(warrior.attack())  # 전사의 일반 공격
print(wizard.attack())   # 마법사의 일반 공격

print(warrior.heavy_attack())  # 전사의 특수 공격
print(wizard.fireball())       # 마법사의 특수 공격

print(warrior.take_damage(30))  # 전사가 피해를 입음
print(wizard.take_damage(20))   # 마법사가 피해를 입음

print(wizard.heal())  # 마법사가 치유 마법 사용

print("=== 게임 종료 ===")

댓글