다중 상속의 슈퍼 호출 세부사항

巴扎黑
풀어 주다: 2016-11-26 09:56:29
원래의
1301명이 탐색했습니다.

참고: 여기서는 Python 3가 운영 환경으로 사용되었으며, 예제는 "python cookbook" 8장에서 가져왔습니다.

파이썬에서는 하위 클래스가 상위 클래스를 초기화하려는 경우 크게 두 가지 방법이 있는데, 첫 번째는 상위 클래스 이름을 직접 전달하는 것이고, 두 번째는 super 메소드를 사용하는 것입니다. 단일 상속에서는 둘 사이에 차이가 없지만 다중 상속에서는 주의해야 할 몇 가지 미묘한 차이점이 있습니다. 예시 설명이 마지막입니다!
1. 상위 클래스 이름을 사용하는 경우:

Python 코드

class Base:

def __init__(self):

print('Base.__init__')

클래스 A(기본):

def __init__(self):

Base.__init__(self)

print('A.__init__')

클래스 B(기본):

def __init__(self):

Base.__init__(self)

print('B.__init__')

class C(A,B):

def __init__(self ):

A.__init__(self)

B.__init__(self)

print('C.__init__')


이것은 클래스 C를 인스턴스화하면 출력은 다음과 같습니다.

Python 코드

>>> c = C()

Base.__init__

A.__init__

Base.__init__

B.__init__

C.__init__

>>>

Base 클래스가 두 번 호출되는 것을 볼 수 있습니다. 이는 대부분의 경우 우리가 원하는 결과가 아니므로 이번에는 super 메소드 사용을 고려해 볼 수 있습니다.

2. super를 사용하는 경우:

Python 코드

class Base:

def __init__(self):

print('Base.__init__')                                                                                                                                             ()

print('A.__init__')

클래스 B(기본):

def __init__ (자체):

super().__init__()

print('B.__init__')

클래스 C(A,B) :

def __init__(self):

super().__init__() # 여기에서는 super()를 한 번만 호출합니다

print('C.__init__')

이때 인스턴스화 클래스 C의 출력은 다음과 같습니다.

Python 코드

>>> >

Base.__init__

B.__init__

A.__init__

C.__init__

>>> 🎜>

베이스를 볼 수 있습니다. 클래스는 한 번만 호출되나요? 하지만 불행하게도 이것이 제가 이 블로그 기록을 쓰게 된 이유는 아닙니다. 주의 깊게 관찰하면 Base 클래스가 실제로 예상대로 한 번만 호출되지만 "B.__init__"가 먼저 출력되고 그 다음에는 Just 출력 " A.__init__"? 그리고 이로 인해 Base가 한 번만 초기화되는 이유는 무엇입니까? 당신도 좀 당황스러울 텐데요, 그렇죠? 사실, 이 모든 것은 다중 상속 중 super 호출 프로세스에 대한 "비난"이어야 합니다. Python이 클래스(상속뿐만 아니라)를 구현할 때 다음 예와 같이 클래스 속성 __mro__를 통해 볼 수 있는 구문 분석 순서 목록을 생성하는 메서드를 생성합니다.

Python Code

>>> C.__mro__

(, , ,

<클래스 '__main__.Base'>, <'객체'>)

>>>


따라서 속성이나 메서드를 검색할 때 이 속성이나 메서드와 일치하는 첫 번째 클래스를 찾을 때까지 이 목록에 따라 각 클래스를 반복합니다. 상속에서 super를 사용하는 경우 인터프리터는 더 이상 super를 만나지 않거나 목록을 순회할 때까지 super를 만날 때마다 목록에서 다음 클래스를 검색한 다음 재귀와 비슷하게 레이어별로 반환합니다. 따라서 이 예의 검색 프로세스는 다음과 같습니다. C에서 super 발견 --> 목록에서 다음 클래스 검색, 즉 A --> A에서 다시 super 발견, B 검색 --> super가 B에 다시 나타남 search Base --> Base 클래스를 초기화하고 재귀적으로 반환합니다.
과정을 더 잘 설명하기 위해 이제 클래스 B의 슈퍼 라인을 주석 처리하세요:

Python 코드

클래스 B(Base):

def __init__(self):

#super().__init__()

print('B.__init__')

class C( A,B):

def __init__(self):

super().__init__() # 여기에서는 super()를 한 번만 호출합니다

print('C. __init__')


클래스 C를 다시 인스턴스화하면 출력은 다음과 같습니다.

Pythonn 코드

>>> )

B.__init__

A.__init__

C.__init__


기본 클래스가 더 이상 출력을 생성하지 않습니다! 왜? B에는 super가 없기 때문에 목록이 Base 클래스 검색을 차단하므로 Base가 초기화되지 않습니다!


원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿