C.W.K.
Stream
Lesson 01 of 05 · published

다중 상속과 MRO

~22 min · mro, multiple-inheritance, c3, super

Level 0호기심
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete

다중 상속 — 깊은 물

Python 은 한 클래스가 여러 부모 상속 가능. class C(A, B): 합법. 즉시 떠오르는 질문 — AB 둘 다 method() 정의하면 C().method() 에서 누가 이김? 답은 *method resolution order* (MRO) — C3 알고리즘으로 계산된 상속 그래프의 결정적 선형화.

C3 알고리즘 — 룰, 증명 X

알고리즘 외울 필요 X. 그게 만드는 룰을 평이하게 — 클래스가 모든 부모보다 먼저 오고, 부모는 작성 순서로. Python 이 이 제약들 트리 전체에 결합해서 단일 순서. Cls.__mro__ 가 보여줘. 제약 만족 안 되면 클래스 정의 시점에 TypeError.

다중 상속의 super() — 협력 호출

단일 상속에서 super().method() 가 부모 메서드 호출. 다중 상속에선 *MRO 의 다음 클래스* 호출 — 부모 아닐 수도. 이게 "협력 다중 상속" — diamond 의 모든 클래스가 super() 호출 가능, 호출이 MRO 순서로 걸어 각 클래스 한 번씩.

원칙: 다중 상속 + super() 섞을 때 체인의 모든 클래스가 **kwargs 받고 forward 해야 해. 한 클래스가 까먹으면 체인 깨져. 협력 다중 상속의 비용 — 그리고 대부분 Python 코드가 합성 선호하는 주된 이유.

Diamond — MRO 가 비자명한 이유

고전 케이스 — DBC 상속, 둘 다 A 상속. MRO 없으면 D().method() 호출 시 A.method 두 번 호출 위험. C3 가 모든 조상이 MRO 에 정확히 한 번 — 모든 로컬 부모 순서와 일관된 순서로.

Code

MRO 들여다보기·python
class A: pass
class B(A): pass
class C(A): pass
class D(B, C): pass

for cls in D.__mro__:
    print(cls.__name__)
# D
# B
# C
# A
# object

# 같은 거 — 정렬된 list:
print([c.__name__ for c in D.mro()])
메서드 해석 동작·python
class A:
    def name(self): return "A"

class B(A):
    def name(self): return "B"

class C(A):
    def name(self): return "C"

class D(B, C):
    pass

print(D().name())          # 'B'   — D 다음 MRO 첫 번째
협력 super() — 모든 클래스 forward·python
class A:
    def __init__(self, **kwargs):
        print("A.__init__")
        super().__init__(**kwargs)

class B(A):
    def __init__(self, **kwargs):
        print("B.__init__")
        super().__init__(**kwargs)

class C(A):
    def __init__(self, **kwargs):
        print("C.__init__")
        super().__init__(**kwargs)

class D(B, C):
    def __init__(self, **kwargs):
        print("D.__init__")
        super().__init__(**kwargs)

D()
# D.__init__
# B.__init__
# C.__init__
# A.__init__
# 각 클래스 한 번씩, MRO 순서로 — super() 덕분
비일관 상속 — Python 이 잡아·python
class A: pass
class B(A): pass
class C(A): pass

# 작동 — D 부모 (B, C), 둘 다 A 가 부모.
class D(B, C): pass

# 안 됨 — 부모 순서 모순
try:
    class Bad(B, C, B):
        pass
except TypeError as e:
    print("MRO 충돌:", e)

External links

Exercise

클래스 계층 구축 — Vehicle, Wheeled(Vehicle), Engined(Vehicle), Car(Wheeled, Engined). 각 클래스가 __init__(**kwargs) 정의 — 클래스 이름 출력 + super().__init__(**kwargs) 호출. Car() 생성하고 MRO 순서 관찰. Car.__mro__ 출력해서 생성 시 본 순서와 일치 확인. 각 클래스 __init__ 에 속성 추가해서 최종 Car() 인스턴스가 4 속성 다 갖도록.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.