파이썬 교재 · 15편 / 27편

파이썬 상속과 super — 클래스 확장

기존 클래스를 부모로 두고 차이만 적기. 코드 재사용의 절정.

기초읽는 시간 6분2026-05-13
Student 와 Premium 클래스 상속 관계를 보여주는 코드 화면

14편의 Student 가 잘 동작합니다. 그런데 이제 "프리미엄 학생" 이라는 새 종류가 등장 — 기본 학생 기능에 더해 멘토링·우선 상담 같은 혜택이 추가됩니다. 처음부터 다시 짤까요? 아닙니다. 기존 Student 가 가진 모든 것을 물려받고, 새로 추가될 것만 적으면 됩니다. 그게 상속(inheritance).

15편을 마치면 ① class Child(Parent): 문법 ② super() 로 부모 초기화 ③ 메서드 오버라이드 ④ isinstance·issubclass ⑤ 다중 상속의 주의점 — 5가지를 손에 익힙니다.

상속 기본 — class Child(Parent)

class Student:
    def __init__(self, name, score):
        self.name = name
        self.score = score

    def greet(self):
        return f"안녕, {self.name}"

    def grade(self):
        return "A" if self.score >= 90 else "B" if self.score >= 80 else "C"

# Premium 은 Student 를 부모로
class Premium(Student):
    pass     # 아무것도 안 적어도 부모의 모든 것 상속

p = Premium("준성", 88)
p.greet()        # '안녕, 준성' — Student 의 메서드 그대로 사용
p.grade()        # 'B'
isinstance(p, Student)   # True — Premium 은 Student 이기도 함

괄호 안에 부모 이름. 자식은 부모의 모든 속성·메서드를 자동으로 갖습니다. 새로 정의할 필요 없이 그대로 쓰면 동작해요.

super() — 부모를 다시 부르기

자식이 자기만의 속성을 추가하고 싶으면 __init__ 을 새로 정의. 그런데 부모의 초기화도 같이 하고 싶다면 super() 로 부모 생성자 호출.

class Premium(Student):
    def __init__(self, name, score, perks):
        super().__init__(name, score)    # 부모 __init__ 먼저
        self.perks = perks                # 자식만의 속성 추가

    def greet(self):                       # 메서드 오버라이드
        base = super().greet()             # 부모 결과를 가져와
        return f"{base} (프리미엄 — {', '.join(self.perks)})"

p = Premium("준성", 88, ["VIP 멘토링", "우선 상담"])
print(p.greet())
# 안녕, 준성 (프리미엄 — VIP 멘토링, 우선 상담)
print(p.grade())   # 'B' — 부모 메서드 그대로

super()"지금 클래스의 부모" 를 가리킵니다. 부모 이름을 직접 적어도(Student.__init__(self, name, score)) 동작하지만, 부모가 바뀔 때 모든 호출을 고쳐야 해서 super() 가 안전합니다.

메서드 오버라이드 — 부모 동작을 새로 정의

같은 이름의 메서드를 자식 클래스에서 다시 정의하면 자식의 것이 우선합니다. 오버라이드(override). 위 greet 가 그 예 — 부모의 결과에 정보를 덧붙였어요.

📌 부모 호출 위치는 보통 맨 처음

super().__init__() 은 자식의 새 속성을 설정하기 전에 부릅니다. 그래야 부모가 설정한 속성을 자식이 참고하거나 덮어쓸 수 있어요. 거꾸로 하면 자식 속성이 사라지는 사고 가능.

isinstance·issubclass — 관계 확인

p = Premium("준성", 88, ["VIP"])
s = Student("수민", 92)

isinstance(p, Premium)      # True
isinstance(p, Student)      # True — 자식은 부모이기도 함
isinstance(s, Premium)      # False — 부모가 자식인 건 아님

issubclass(Premium, Student)   # True
issubclass(Student, Premium)   # False

# 함수에서 자료형 분기
def describe(x):
    if isinstance(x, Premium):
        return "프리미엄 회원"
    if isinstance(x, Student):
        return "일반 회원"
    return "회원 아님"

type(p) == Student 같은 비교는 상속 관계를 무시해서 거의 안 씁니다. isinstance 가 표준.

다중 상속 — 가능은 하지만 조심

파이썬은 부모를 여러 개 둘 수 있습니다. 하지만 이게 "다이아몬드 문제" 라 불리는 복잡성을 만들어요.

class A:
    def hi(self): return "A"

class B:
    def hi(self): return "B"

class C(A, B):
    pass

c = C()
c.hi()    # 'A' — 왼쪽 부모 우선 (MRO 규칙)

여러 부모에 같은 메서드가 있으면 왼쪽이 우선. 이 순서를 MRO(Method Resolution Order) 라 부르고, C.__mro__ 로 확인 가능. 입문자 단계에서는 다중 상속은 피하라 가 안전한 조언입니다. "is-a" 가 명확한 단일 상속만 쓰고, 여러 기능 합성은 다른 패턴(구성·믹스인)으로.

⚠️ 상속을 너무 좋아하지 마세요. 입문자가 OOP 를 배우면 모든 걸 상속으로 풀려고 합니다. 실은 "is-a"(고양이는 동물이다) 관계가 명확할 때만 써야 해요. "has-a"(자동차는 엔진을 가진다) 는 상속이 아니라 구성(composition) — 다른 객체를 속성으로 갖는 게 더 깔끔. "Favor composition over inheritance" 가 OOP 격언.

실전 패턴 + 마무리

# 추상 부모 + 구체 자식
class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        raise NotImplementedError("자식이 구현하세요")

class Dog(Animal):
    def speak(self):
        return f"{self.name}: 멍멍"

class Cat(Animal):
    def speak(self):
        return f"{self.name}: 야옹"

for a in [Dog("뽀삐"), Cat("나비")]:
    print(a.speak())
# 뽀삐: 멍멍 / 나비: 야옹

같은 인터페이스(speak) 를 강제하면서 구체 구현은 자식에게 맡기는 패턴. 다양한 객체를 같은 방식으로 처리할 수 있게 해줘서 자동화 코드에서 자주 만납니다.

다음 미션 — REPL 에서: ① Vehicle 부모와 Car·Bicycle 자식 (속도 메서드 다르게) ② super() 로 부모 메서드 결과 활용하는 오버라이드 ③ isinstance 로 리스트 안 객체 종류별 카운트.

다음 편 미리보기

16편 — "가상환경 venv": 프로젝트마다 독립된 파이썬 환경. python -m venv·activate·requirements.txt.

📚 27편 파이썬 교재 시리즈 — 15/27편
← 14편 "클래스 입문" · 다음: 16편 "가상환경 venv"

© 2026 주나이테크(주) @JUNAITECH