Python: 슈퍼 당신은 몰라요

高洛峰
풀어 주다: 2016-11-15 15:14:37
원래의
1160명이 탐색했습니다.

super() 사용 소개

클래스 상속에서 메서드를 재정의하면 해당 메서드가 상위 클래스의 동일한 이름의 메서드를 재정의하지만 때로는 다음과 같은 기능을 구현하기를 바랍니다. 동시에 부모 클래스의 메소드를 호출해야 합니다. 이는 super를 사용하여 달성할 수 있습니다.

class Animal(object):
    def __init__(self, name):
        self.name = name
    def greet(self):
        print 'Hello, I am %s.' % self.name

class Dog(Animal):
    def greet(self):
        super(Dog, self).greet()   # Python3 可使用 super().greet()
        print 'WangWang...'
로그인 후 복사

위에서 Animal은 부모 클래스인 Dog는 하위 클래스이므로 Dog 클래스에서 반복합니다. Greeting 메서드는 부모 클래스의 기능을 동시에 구현하기 위해 부모 클래스의 메서드도 호출합니다. :

>>> dog = Dog('dog')
>>> dog.greet()
Hello, I am dog.
WangWang..
로그인 후 복사

super의 가장 일반적인 용도 중 하나는 하위 클래스에 있다고 할 수 있습니다. 다음과 같이 상위 클래스의 초기화 메서드를 호출합니다.

class Base(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b

class A(Base):
    def __init__(self, a, b, c):
        super(A, self).__init__(a, b)  # Python3 可使用 super().__init__(a, b)
        self.c = c
로그인 후 복사

super( )

위의 사용법을 읽고 나면 super의 사용법이 매우 간단하다는 것을 느낄 수 있습니다. 상위 클래스를 가져와서 상위 클래스의 메서드를 호출하는 것 외에는 아무것도 아닙니다. 실제로 위의 경우에는 super가 획득한 클래스가 우연히 부모 클래스가 되지만, 다른 경우에는 Super가 실제로 부모 클래스와 실질적인 관계가 없는 것은 아닙니다.

다중 상속과 관련된 좀 더 복잡한 예를 살펴보겠습니다.

class Base(object):
    def __init__(self):
        print "enter Base"
        print "leave Base"

class A(Base):
    def __init__(self):
        print "enter A"
        super(A, self).__init__()
        print "leave A"

class B(Base):
    def __init__(self):
        print "enter B"
        super(B, self).__init__()
        print "leave B"

class C(A, B):
    def __init__(self):
        print "enter C"
        super(C, self).__init__()
        print "leave C"
로그인 후 복사

그 중 Base가 상위 클래스이고 A와 B가 Base를 상속하고, C는 A, B를 상속하며, 이들의 상속 관계는 다음과 같습니다.

      Base
      /  \
     /    \
    A      B
     \    /
      \  /
       C
로그인 후 복사

이제 사용법을 살펴보겠습니다.

>>> c = C()
enter C
enter A
enter B
enter Base
leave Base
leave B
leave A
leave C
로그인 후 복사

super가 " call the method of the parent class"라고 입력하면 enter A의 다음 문장이 왜 enter Base가 아니고 enter B인지 궁금할 것입니다. 그 이유는 super가 부모 클래스와 실질적인 관계가 없기 때문입니다. 이제 super가 어떻게 작동하는지 알아 보겠습니다.

MRO 목록

실제로 정의한 각 클래스에 대해 Python은 클래스 상속 순서를 나타내는 MRO(메서드 해결 순서) 목록을 계산합니다. 다음 메서드를 사용할 수 있습니다. 특정 클래스의 MRO 목록을 얻으려면:

>>> C.mro()   # or C.__mro__ or C().__class__.mro()
[__main__.C, __main__.A, __main__.B, __main__.Base, object]
로그인 후 복사

이 MRO 목록의 순서는 어떻게 결정됩니까? 이는 C3 선형화 알고리즘을 통해 구현됩니다. 일반적으로 클래스의 MRO 목록은 모든 상위 클래스의 MRO 목록을 병합하고 다음 세 가지 원칙을 따르는 것입니다.

하위 클래스는 항상 상위 클래스보다 앞에 있습니다. 🎜>

부모 클래스가 여러 개인 경우 목록의 순서에 따라 검사합니다.

다음 클래스에 합법적인 선택이 2개인 경우 첫 번째 부모 클래스가 선택됩니다.

super 원칙

super는 다음과 같이 작동합니다.

def super(cls, inst):
    mro = inst.__class__.mro()
    return mro[mro.index(cls) + 1]
로그인 후 복사
그 중 cls는 클래스를 나타내고 inst는 인스턴스를 나타냅니다.

Get inst의 MRO 목록

현재 MRO 목록에서 cls의 인덱스를 찾아 다음 클래스인 mro[index + 1]를 반환합니다.

사용할 때 super(cls, inst), Python은 inst의 MRO 목록에서 cls의 다음 클래스를 검색합니다.

이제 앞의 예로 돌아가 보겠습니다.

먼저 C 클래스의 __init__ 메서드를 살펴보세요.

super(C, self).__init__()
로그인 후 복사
여기서 self는 C의 현재 인스턴스입니다. self.__class__.mro()의 결과는 다음과 같습니다.

[__main__.C, __main__.A, __main__.B, __main__.Base, object]
로그인 후 복사
보시다시피 C의 다음 클래스는 A이므로 A의 __init__로 점프합니다. 이때 Enter A가 출력되고 다음 코드 줄이 실행됩니다.

super(A, self).__init__()
로그인 후 복사
여기서 self도 현재 C 인스턴스의 경우 MRO 목록은 위와 동일합니다. MRO에서 A의 다음 클래스를 검색하면 B입니다. __init__ of B. 이때 Enter Base 대신 Enter B가 출력됩니다.

전체 과정은 상대적으로 명확합니다. super가 상위 클래스의 메소드를 호출한다고 당연하게 여기기보다는 super가 어떻게 작동하는지 이해하는 것이 핵심입니다.

요약

사실 super는 부모 클래스와 실질적인 관계가 없습니다.

super(cls, inst)는 inst의 MRO 목록에서 cls의 다음 클래스를 가져옵니다.


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