참고: 여기서는 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를 사용하는 경우:
이때 인스턴스화 클래스 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가 초기화되지 않습니다!