262

이 질문에는 이미 답변이 있습니다.

이것을 고려해보십시오 - A에서 상속받은 B 클래스, B에서 상속받은 C 클래스, 생성자에서 부모 클래스 생성자를 호출하는 일반적인 방법은 무엇입니까? 그래도 여전히 너무 애매한 경우 여기에 몇 가지 코드가 있습니다.

class A(object):
    def __init__(self):
        print "Constructor A was called"

class B(A):
    def __init__(self):
        super(B,self).__init__()
        print "Constructor B was called"

class C(B):
    def __init__(self):
        super(C,self).__init__()
        print "Constructor C was called"

c = C()

이것이 내가 지금하는 방법이다. 그러나 여전히 너무 비 범용적인 것으로 보입니다. 올바른 유형을 수동으로 전달해야합니다.

자, 나는self.__class__super ()에 대한 첫 번째 인수로 사용되지만 분명히 작동하지 않습니다. C의 생성자에 넣으면 B의 생성자가 호출됩니다. B에서 똑같이하면 "self"는 여전히 C의 인스턴스를 가리 키므로 결국 B의 생성자를 다시 호출하게됩니다 (이 작업은 무한 재귀에서 끝납니다).

지금 다이아몬드 상속에 대해 생각할 필요가 없습니다. 저는이 특정 문제를 해결하는 데 관심이 있습니다.


  • "하지만 여전히 너무 비사 제적 인 것 같습니다. 올바른 유형을 수동으로 전달해야합니다. " 클래스 이름을 super ()로 전달합니다. 수퍼 클래스 또는 다른 것을 알 필요가 없습니다. 이것은 비 제너릭 (non-generic) 인 방법은 무엇입니까? 어떤 문제가 발생합니까? 이 부분이 깨지는 사례를 줄 수 있습니까? - S.Lott
  • 나는이 질문에 답할 준비가되어 있지 않다. 하지만 어쨌든 클래스 이름이 변경되면 어떻게 될까요? 이런 종류의 체인을 자동화하는 데코레이터 함수를 작성하고자한다면 어떻게해야할까요? 이제는 이것이 불가능하다는 것을 알았지 만 질문을 할 때 나는 그것을 알지 못했습니다. - shylent
  • @shylent, 내가 당신의 질문을 이해한다면, 당신의 설명이 가능합니다. mro 이해한다면 super ()를 사용하여 부모 참조를 완전히 일반화 할 수 있습니다. Google " python super is super ", 동영상을보세요. - Jamie Marshall
  • @ 실제로 실재, 당신의 질문을 다시 읽으면 나는 당신이 겪고있는 무한 재귀가 당신이 생각하는 것과 다르다고 믿는다. 나는 mro 명령으로 당신이 의도하지 않은 생성자를 호출한다고 생각합니다. 나는 그저 오래 전에이 같은 일을 처리했다. super의 첫 번째 인수에 무엇을 전달하더라도 슈퍼는 mro에서 첫 번째 생성자를 호출합니다. 예를 들어 전달 된 형식이 아닙니다. 예를 들어 C의 생성자에서 super (self .__ class__, self)를 호출하면 그것은 BRO의 생성자를 여전히 mro의 첫 번째 부모이기 때문에 호출합니다. - Jamie Marshall

3 답변


161

실제로 파이썬 2.x에서 사용하는 방식을 권장합니다.

클래스가 명시 적으로 전달되는지 여부에 대한 문제super기능보다는 스타일의 문제입니다. 수업을 들으려면super파이썬의 철학은 "암묵적보다 낫다"라는 철학에 적합합니다.


  • 받아들이는 대답을 결정하기가 힘들었지 만, 사용하고있는 파이썬 버전과 관련이 있기 때문에 받아 들일 것입니다. - shylent
  • 파이썬 2.6에서는TypeError: super() argument 1 must be type, not classobj이 방법을 사용합니다. 내가 놓친 게 있니? - Leopd
  • @Leopd :super()새로운 스타일의 클래스에서만 작동합니다. 즉,에서 상속해야합니다.object. - dF.
  • 파이썬은 강력한 형식의 언어이지만 동적으로 형식이 지정됩니다. 약한 타이핑과 동적 타이핑에는 차이가 있습니다. - Josh Smeaton
  • @ TheScienceBoy 정의는 분명하다. 파이썬은 강력합니다. Java와 같은 것은 강력한 정적입니다. PHP는 약한 동적입니다. 정적 타이핑은 입력 매개 변수가 올바른 유형임을 보장합니다 (적어도 일부 제한 내에서). 강력한 타이핑이란 컴파일러 / 런타임이하나의 타입을 다른 타입으로 변경하는 것. 1로 설정하면 수학을 할 수 있습니다. 여기를 참조하십시오 :wiki.python.org/moin/… - Josh Smeaton

176

파이썬 3에는 다음과 같이 사용할 수있는 향상된 super ()가 포함되어 있습니다 :

super().__init__(args)


  • 두 개 이상의 부모 클래스가있는 경우 슈퍼 클래스에서 호출 할 부모 클래스를 어떻게 식별 할 수 있습니까? - Kracekumar
  • @kracekumar 그것은 클래스에 의해 결정됩니다 ' MRO (Method Resolution Order)는 전화를 통해 확인할 수 있습니다.MyClassName.mro(). 내가 틀릴 수도 있지만 첫 번째 지정된 부모가__init__호출됩니다. - Cam Jackson
  • @ironfroggy, 당신이 정교하게 생각해 줍니 까? 방금이 낡은 실을 발견했고 똑같은 질문을했습니다. 또한이 질문이 처음으로 제기 된 이후로 Python 2.x에서 개선 된 점이 있습니까? - Amelio Vazquez-Reina
  • @ user815423426 up-calls를보다 일반적인 것으로 만들었 기 때문에 더 이상 원래 질문의 주제 인 클래스 이름을 반복하지 않습니다. - ironfroggy
  • @kracekumar, super (X, obj)는 실제로 특별한 "슈퍼" 속성 액세스를 수행 할 때 클래스 X에 속성이 전혀없는 경우 반환 된 속성을 반환합니다. 예를 들어 super (X, obj) .__ init__은초기화귀하의 obj의 메소드처럼초기화클래스 X에 없었습니다. 이제 클래스 X가 두 개의 부모를 가지고 있고 X.__ init__이 존재하지 않으면, 기본 동작은초기화오직하나두 가지가 아니라 부모의 이것은 슈퍼가하고있는 것입니다 ... 당신에게 부모 중 한 명을줍니다. - Chris Cogdon

24

다음과 같이 간단하게 작성할 수 있습니다.

class A(object):

    def __init__(self):
        print "Constructor A was called"

class B(A):

    def __init__(self):
        A.__init__(self)
        #A.__init__(self,<parameters>) if you want to call with parameters
        print "Constructor B was called"

class C(B):

    def __init__(self):
        #A.__init__(self) #if you want to call most super class...
        B.__init__(self)
        print "Constructor C was called"

연결된 질문


관련된 질문

최근 질문