파이썬 상속과 super — 클래스 확장
기존 클래스를 부모로 두고 차이만 적기. 코드 재사용의 절정.
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" 가 명확한 단일 상속만 쓰고, 여러 기능 합성은 다른 패턴(구성·믹스인)으로.
실전 패턴 + 마무리
# 추상 부모 + 구체 자식
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.
← 14편 "클래스 입문" · 다음: 16편 "가상환경 venv"