← 파이썬 강의 목록으로
⚙️
중급 (Intermediate)
extends · super · __str__ · __eq__ · classmethod

8주차 — 객체지향 (2) — 상속·다형성·매직 메서드

부모 클래스의 속성·메서드를 물려받는 상속, super() 호출, 다형성, __str__/__eq__/__add__ 같은 매직 메서드 오버라이딩, classmethod와 staticmethod까지.

inheritancesupermagicclassmethod
소요 시간
2시간
난이도
📊 중급
선수 조건
🎯 7주차 (OOP 1)
결과물
Shape→Rectangle/Circle, Vector + 매직 메서드

이 강의에서 배우는 것

  • 1클래스 상속과 super() 를 사용한다
  • 2다형성을 코드로 보인다
  • 3매직 메서드를 오버라이딩한다
  • 4클래스 메서드와 정적 메서드를 구분한다

1. 상속

python
class Animal:
    def __init__(self, name):
        self.name = name
    def speak(self):
        return "..."

class Dog(Animal):     # Animal 상속
    def speak(self):   # 메서드 오버라이딩
        return "멍멍"

d = Dog("바둑이")
print(d.name, d.speak())   # 바둑이 멍멍

2. super()

python
class Puppy(Dog):
    def __init__(self, name, age):
        super().__init__(name)   # 부모 __init__ 호출
        self.age = age

3. 다형성

같은 메서드 이름을 다양한 클래스에서 다르게 구현. 호출자는 타입을 신경 쓰지 않음.

python
animals = [Dog("바둑이"), Cat("나비"), Cow("얼룩이")]
for a in animals:
    print(a.speak())   # 멍멍 / 야옹 / 음매

4. 매직 메서드

이름이 __xxx__ 로 시작·끝나는 특별 메서드. 파이썬 문법과 연결됨.

메서드트리거
__str__str(x), print(x)
__repr__REPL에서 표시, repr(x)
__len__len(x)
__eq__x == y
__add__x + y
__getitem__x[i]
__iter__/__next__for ... in x
python
class Point:
    def __init__(self, x, y):
        self.x, self.y = x, y
    def __repr__(self):
        return f"Point({self.x}, {self.y})"
    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)
    def __eq__(self, other):
        return (self.x, self.y) == (other.x, other.y)

p = Point(1, 2) + Point(3, 4)
print(p)              # Point(4, 6)
print(p == Point(4, 6))   # True

5. classmethod / staticmethod

python
class Date:
    def __init__(self, y, m, d):
        self.y, self.m, self.d = y, m, d

    @classmethod
    def from_string(cls, s):
        y, m, d = map(int, s.split("-"))
        return cls(y, m, d)        # 인스턴스 생성

    @staticmethod
    def is_valid(y, m, d):
        return 1 <= m <= 12 and 1 <= d <= 31

print(Date.from_string("2026-05-09").y)
print(Date.is_valid(2026, 5, 9))

6. 자주 하는 실수

  1. super().__init__() 누락 — 부모 속성이 초기화 안 됨
  2. 매직 메서드를 일반 호출 — p.add(q) 가 아니라 p + q
  3. __eq__ 만 만들고 __hash__ 빼먹음 — set/dict 키로 못 씀
  4. 다중 상속 남용 — 가능하지만 복잡. 가능하면 컴포지션

7. FAQ

Q1. 추상 클래스(인터페이스) 만들려면?

abc.ABC 와 @abstractmethod 사용.

Q2. __str__ vs __repr__ ?

__str__ 은 사람용, __repr__ 은 개발자용 (디버깅). 보통 __repr__ 만 정의해도 됨.

Q3. 상속 vs 컴포지션?

"is-a" 관계면 상속, "has-a" 면 속성 보유 (컴포지션). 의심되면 컴포지션.

💻 예제 (examples)

실제로 실행해 결과를 확인할 수 있는 예제 코드입니다.

01_inherit.py상속 + super
CODE
class Animal:
    def __init__(self, name):
        self.name = name
    def speak(self):
        return "..."

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)
        self.breed = breed
    def speak(self):
        return "멍멍"

d = Dog("바둑이", "진돗개")
print(d.name, d.breed, d.speak())
▶ 실행 결과
바둑이 진돗개 멍멍
02_polymorphism.py다형성
CODE
class Animal:
    def speak(self): return "..."

class Dog(Animal):
    def speak(self): return "멍멍"

class Cat(Animal):
    def speak(self): return "야옹"

class Cow(Animal):
    def speak(self): return "음매"

for a in [Dog(), Cat(), Cow()]:
    print(a.speak())
▶ 실행 결과
멍멍
야옹
음매
03_magic.py매직 메서드 (Point)
CODE
class Point:
    def __init__(self, x, y):
        self.x, self.y = x, y
    def __repr__(self):
        return f"Point({self.x}, {self.y})"
    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)
    def __eq__(self, other):
        return (self.x, self.y) == (other.x, other.y)

p = Point(1, 2) + Point(3, 4)
print(p)
print(p == Point(4, 6))
print([Point(0,0), p])  # __repr__ 활용
▶ 실행 결과
Point(4, 6)
True
[Point(0, 0), Point(4, 6)]
04_classmethod.pyclassmethod / staticmethod
CODE
class Date:
    def __init__(self, y, m, d):
        self.y, self.m, self.d = y, m, d

    @classmethod
    def from_string(cls, s):
        y, m, d = map(int, s.split("-"))
        return cls(y, m, d)

    @staticmethod
    def is_valid(y, m, d):
        return 1 <= m <= 12 and 1 <= d <= 31

dt = Date.from_string("2026-05-09")
print(dt.y, dt.m, dt.d)
print(Date.is_valid(2026, 13, 1))
▶ 실행 결과
2026 5 9
False

📝 과제 (exercises)

직접 풀어보고, 막힐 때 정답을 펼쳐 비교해보세요.

과제 1

Shape 추상 → Rectangle, Circle

목표: Shape 클래스를 상속해 Rectangle, Circle 구현.

요구사항
  • Shape — area() 메서드 (기본 구현은 0 또는 abstract)
  • Rectangle, Circle — area 오버라이딩
  • 도형 리스트를 순회해 면적 출력
입출력 예시
Rectangle: 200
Circle: 78.54
정답 코드 펼치기 / 접기
SOLUTION
import math

class Shape:
    def area(self):
        return 0

class Rectangle(Shape):
    def __init__(self, w, h):
        self.w, self.h = w, h
    def area(self):
        return self.w * self.h

class Circle(Shape):
    def __init__(self, r):
        self.r = r
    def area(self):
        return math.pi * self.r ** 2

shapes = [Rectangle(10, 20), Circle(5)]
for s in shapes:
    print(f"{type(s).__name__}: {s.area():.2f}")
▶ 실행 결과
Rectangle: 200.00
Circle: 78.54
과제 2

Playlist 클래스 + 매직 메서드

목표: 노래 리스트로 __len__, __getitem__, __add__ 구현.

요구사항
  • songs 속성에 곡 리스트
  • len(p), p[0], p1 + p2 동작
입출력 예시
len: 3
첫 곡: 봄날
합치기 후 len: 5
정답 코드 펼치기 / 접기
SOLUTION
class Playlist:
    def __init__(self, songs=None):
        self.songs = list(songs) if songs else []

    def __len__(self):
        return len(self.songs)

    def __getitem__(self, i):
        return self.songs[i]

    def __add__(self, other):
        return Playlist(self.songs + other.songs)

p1 = Playlist(["봄날", "Spring Day", "FAKE LOVE"])
p2 = Playlist(["DNA", "Butter"])
print(f"len: {len(p1)}")
print(f"첫 곡: {p1[0]}")
print(f"합치기 후 len: {len(p1 + p2)}")
▶ 실행 결과
len: 3
첫 곡: 봄날
합치기 후 len: 5
과제 3

Vector 클래스 (+, -, ==, repr)

목표: 2D 벡터 합·차·비교·표현.

요구사항
  • x, y 속성
  • __add__, __sub__, __eq__, __repr__
입출력 예시
Vector(4, 6)
Vector(-2, -2)
True
정답 코드 펼치기 / 접기
SOLUTION
class Vector:
    def __init__(self, x, y):
        self.x, self.y = x, y
    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)
    def __sub__(self, other):
        return Vector(self.x - other.x, self.y - other.y)
    def __eq__(self, other):
        return (self.x, self.y) == (other.x, other.y)
    def __repr__(self):
        return f"Vector({self.x}, {self.y})"

a = Vector(1, 2)
b = Vector(3, 4)
print(a + b)
print(a - b)
print(a + b == Vector(4, 6))
▶ 실행 결과
Vector(4, 6)
Vector(-2, -2)
True
예제 코드 / 강의 자료

전체 강의 자료와 예제 코드는 GitHub에서 자유롭게 받아볼 수 있습니다.

GitHub에서 보기 ↗