Python MRO의 동적 특성
8604 단어 ooppythonarchitecture
class Base:
def chain(self):
return 'Base'
class A(Base):
...
class B(Base):
def chain(self):
return f"{super().chain()} <- B"
class C(A, B):
pass
class D(C):
def chain(self):
return f"{super().chain()} <- D"
chain
인스턴스에서 D
를 호출하면 다음 문자열이 생성됩니다.In [1]: d.chain()
Out[1]: 'Base <- B <- D'
다음 코드가 실행되면 어떻게 될까요?
In [2]: A.chain = A.chain
공격적이지 않죠? 이제
d.chain()
다시 전화해 보세요...In [3]: d.chain()
Out[3]: 'Base <- D'
D
의 메서드 확인 순서(MRO, 메서드 및 속성을 확인할 때 Python이 찾는 클래스의 순서)를 살펴보겠습니다.In [4]: D.mro()
Out[4]: [__main__.D, __main__.C, __main__.A, __main__.B, __main__.Base, object]
D.chain()
를 호출하면 Python은 이 목록을 살펴보고 chain
가 클래스의 구성원으로 있는 첫 번째 인스턴스를 반환합니다. 이 예에서 D
는 chain
를 구현합니다.D.chain
가 차례로 super().chain()
를 호출합니다. 파이썬은 무엇을 할 것인가? D
에서 다음 클래스를 가져와 이 새 목록에서 chain
를 찾으려고 합니다. C
구현하지 않습니다. 그렇지 않습니다 A
. B
그렇지! 결과는 B.chain
반환하는 것과 비트 " <- D"
를 더한 것입니다.B.chain
는 super()를 다시 호출합니다... 우리는 우리가 무엇을 하는지 알고 있습니다. Base가 이를 구현하고 더 이상 super()
호출이 없습니다. 따라서 Base.chain
반환 "Base"
, B.chain()
반환 "Base <- B"
및 D.chain()
최종 반환 "Base <- B <- D"
있습니다.그래서 우리가
A.chain = A.chain
후에 무슨 일이 일어나고 있습니까? B.chain()
가 무시되는 이유는 무엇입니까? 무슨 일이 일어나고 있는지 분석해 봅시다. A
의 MRO는?In [5]: A.mro()
Out[5]: [__main__.A, __main__.Base, object]
아주 간단합니다.
A.chain
하면 어떻게 되나요? 파이썬은 그것을 구현하지 않는 A
를 볼 것입니다. 그러나 Base
는 그것을 구현하므로 이것이 사용할 구현입니다. 그러나 우리가 과제를 수행할 때 무슨 일이 벌어지고 있습니까?Python은 이 할당을 오른쪽에서 왼쪽으로 평가합니다.
A.chain = A.chain
그런 다음 "find chain
for A"를 의미하며, 이는 Base.chain
를 반환합니다. 그러면 파이썬은 클래스 A에 chain
라는 새 멤버를 효과적으로 생성합니다!D의 MRO로 돌아가 보겠습니다.
[__main__.D, __main__.C, __main__.A, __main__.B, __main__.Base, object]
이 클래스가 생성된 방식으로
A
의 멤버는 B
전에 테스트됩니다! 해결 순서는 무엇을 의미합니까? D.chain()
가 super().chain()
를 호출하면 A
의 새로 추가된 멤버를 잡아 호출합니다. 그리고 A
의 관점에서 구현은 Base.chain
호출이 없는 super()
와 동일합니다! 🤯이것은 Python의 동적 특성으로 인해 발생합니다. The entry for
super()
in Python's documentation 이 문제에 대한 놀라운 설명과 Python의 특성으로 인해 고유한 사용 사례가 있는 방법이 있습니다.Python의 다중 상속 기능과 동적 특성으로 인해 실제 메서드 확인 순서와 클래스 계층 구조는 런타임에만 알려지고 응용 프로그램 수명 동안 언제든지 변경될 수 있습니다.
수업 디자인은 협력적이어야 합니다. 위의 예에는 많은 문제가 있습니다but there is a simple set of rules that help designing collaborative classes.
여기서 요점은
super()
에 의해 호출된 메서드의 실제 구현은 런타임에만 알려져 있으며 정적으로 쉽게 정의할 수 없다는 것입니다.클래스를 공동으로 설계하고 런타임에 클래스의 변형을 관찰합니다.
Python의 MRO에 대해 더 알고 싶으십니까? Python 문서의 이 놀라운 기사는 버전 2.3 이후에 알고리즘이 어떻게 작동하는지 소개합니다. Check it out !
이것은 내 첫 번째 dev.to 게시물입니다. 이 문제를 개선하기 위해 제가 할 수 있는 일이 있으면 알려주세요!
Adam Śmigielski에 Unsplash의 사진
Reference
이 문제에 관하여(Python MRO의 동적 특성), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/rbusquet/the-dynamic-nature-of-python-s-mro-22on텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)