프로그래밍시니어 파이썬 개발자

파이썬에서 다중 상속이란 무엇이며, 그 발생에 대한 역사적 원인은 무엇이며, 파이썬은 메소드의 우선 순위 충돌을 어떻게 해결합니까?

Hintsage AI 어시스턴트로 면접 통과

답변

질문의 역사

다중 상속 — 클래스가 여러 부모 클래스에서 동시에 상속될 수 있는 능력 — 이는 OOP의 다른 언어(예: C++)에서 영감을 받아 파이썬에 도입되었습니다. 이것은 재사용 가능한 믹스인을 만드는 데 도움이 됩니다. 메소드 검색 메커니즘(MRO)의 개발에는 많은 시간이 소요되었으며, 메소드 충돌 시 예측 가능성을 보장하기 위해 노력했습니다.

문제

클래스는 서로 다른 기본 클래스에서 동일한 이름을 가진 메소드를 받을 수 있습니다. 호출 시 어떤 메소드를 사용해야 할까요? 명확한 스킴이 없다면 이는 찾기 힘든 오류로 이어질 수 있습니다.

해결책

파이썬은 충돌 해결 시 메소드 검색의 엄격한 순서를 정의하는 C3 정렬 알고리즘을 구현합니다. super() 함수와 클래스의 __mro__ 메소드를 사용하여 상속 체인을 분석하면 모든 것이 명확해집니다.

코드 예:

class A: def foo(self): print("A") class B(A): def foo(self): print("B") super().foo() class C(A): def foo(self): print("C") super().foo() class D(B, C): def foo(self): print("D") super().foo() D().foo() print(D.__mro__)

주요 특징:

  • 파이썬은 메소드 탐색 순서를 구축하기 위해 C3 정렬을 적용합니다(MRO);
  • super()는 특정 부모가 아니라 MRO 체인 내에서 다음 클래스를 참조할 수 있게 해줍니다;
  • MRO 순서는 클래스 속성 __mro__를 통해 확인할 수 있습니다;

함정 질문.

부모 메소드의 이름이 일치하면 어떻게 됩니까?

답: 메소드는 MRO에 정의된 순서로 호출됩니다. 요구하는 이름의 첫 번째 메소드가 호출됩니다.

명시적으로 self를 전달하지 않고 super()를 사용할 수 있습니까?

답: 파이썬 3에서는 가능하며, 클래스 메소드 본문 내에서 super().method() 호출은 명시적 super(클래스, self).method()와 동일합니다.

기존 클래스의 MRO 순서를 변경할 수 있습니까?

답: 클래스가 선언된 이후 MRO 순서는 정적이지만 조사하거나 다른 상속 순서를 가진 새 클래스를 만들 수 있습니다.

일반적인 오류 및 안티패턴

  • super() 호출을 잊어버려 "체인"이 끊기고 초기화가 누락될 수 있습니다;
  • 부모 메소드를 직접 호출하는 것(예: Parent.method(self))은 MRO를 깨트립니다;
  • 모순된 순서를 갖는 복잡한 계층 구조를 생성하면 MRO 오류(TypeError: 일관된 메소드 해결 순서(MRO)를 생성할 수 없습니다.)가 발생합니다;

실제 예

부정적 사례

프로젝트에서 비슷한 메소드를 가진 두 개의 믹스인을 만들었고, 상속 클래스가 두 믹스인을 모두 사용하지만 메소드를 클래스 이름을 통해 직접 호출하여 이벤트 순서가 어긋났습니다.

장점:

  • 메소드가 어디서 호출되는지가 명확합니다.

단점:

  • MRO가 깨져서 모든 메소드가 호출되지 않으며, 기본 클래스 간의 충돌로 인한 버그가 발생합니다.

긍정적 사례

각 믹스인의 메소드에서 super()를 사용하여 체인 내에서 호출되도록 보장합니다. 필요한 동작을 생략하지 않습니다.

장점:

  • 예측 가능한 실행, 클래스 구조를 쉽게 변경할 수 있습니다.
  • 유지 보수가 용이하며, 새로운 믹스인을 쉽게 도입할 수 있습니다.

단점:

  • super()와 MRO 원리를 이해하기 위한 규율과 이해가 필요합니다.