다중 상속 실습하기
Python 에서는 하나의 클래스가 둘 이상의 부모 클래스로부터 상속받는 것이 가능합니다. 이를 **다중 상속 (multiple inheritance)**이라고 합니다. 이는 서로 다른 소스의 기능들을 혼합하는 강력한 도구가 될 수 있지만, 특히 메서드 이름이 동일할 때 Python 이 어느 부모의 메서드를 사용할지 결정하는 방식 때문에 복잡성을 야기하기도 합니다.
이러한 검색 순서를 **메서드 결정 순서 (Method Resolution Order, MRO)**라고 합니다. Python 은 일관되고 예측 가능한 MRO 를 결정하기 위해 C3 선형화 (C3 linearization) 라는 알고리즘을 사용합니다.
새로운 예제를 통해 이를 탐구해 보겠습니다. 파일 탐색기에서 multiple_inheritance.py 파일을 열고 다음 코드를 추가하십시오.
## File: multiple_inheritance.py
class ParentA:
def speak(self):
print("Speaking from ParentA")
def common_method(self):
print("ParentA's common method")
class ParentB:
def speak(self):
print("Speaking from ParentB")
def common_method(self):
print("ParentB's common method")
## Child 는 A 를 상속받고, 그 다음 B 를 상속받습니다
class Child_AB(ParentA, ParentB):
pass
## Child 는 B 를 상속받고, 그 다음 A 를 상속받습니다
class Child_BA(ParentB, ParentA):
def common_method(self):
print("Child_BA's own common method")
if __name__ == "__main__":
child1 = Child_AB()
child2 = Child_BA()
print("--- Child_AB (ParentA, ParentB) 조사 ---")
child1.speak()
child1.common_method()
## .mro() 메서드는 메서드 결정 순서를 보여줍니다
print("MRO for Child_AB:", [c.__name__ for c in Child_AB.mro()])
print("\n--- Child_BA (ParentB, ParentA) 조사 ---")
child2.speak()
child2.common_method()
print("MRO for Child_BA:", [c.__name__ for c in Child_BA.mro()])
파일을 저장합니다. 여기서 Child_AB는 ParentA를 상속받고 그 다음 ParentB를 상속받습니다. Child_BA는 역순으로 상속받습니다. 메서드가 호출되면 Python 은 MRO 에 지정된 순서대로 해당 메서드를 검색합니다.
터미널에서 스크립트를 실행합니다.
python multiple_inheritance.py
다음과 같은 출력을 보게 될 것입니다.
--- Investigating Child_AB (ParentA, ParentB) ---
Speaking from ParentA
ParentA's common method
MRO for Child_AB: ['Child_AB', 'ParentA', 'ParentB', 'object']
--- Investigating Child_BA (ParentB, ParentA) ---
Speaking from ParentB
Child_BA's own common method
MRO for Child_BA: ['Child_BA', 'ParentB', 'ParentA', 'object']
출력 결과에서 다음 사항을 관찰할 수 있습니다.
child1.speak()는 Child_AB의 MRO 에서 ParentA가 먼저 오기 때문에 ParentA의 메서드를 호출합니다.
child2.speak()는 Child_BA의 MRO 에서 ParentB가 먼저 오기 때문에 ParentB의 메서드를 호출합니다.
child2.common_method()는 Child_BA에 직접 정의된 버전을 호출합니다. Python 이 부모 클래스를 확인하기 전에 여기서 먼저 찾기 때문입니다.
다중 상속 시나리오에서 동작을 예측하려면 MRO 를 이해하는 것이 매우 중요합니다.