[python] __init __ ()가 부모 클래스의 __init __ ()을 호출해야합니까?

나는 Objective-C 에서이 구성을 얻었습니다.

- (void)init {
    if (self = [super init]) {
        // init class
    }
    return self;
}

파이썬은 부모 클래스의 구현을 호출해야합니까 __init__?

class NewClass(SomeOtherClass):
    def __init__(self):
        SomeOtherClass.__init__(self)
        # init class

이것은에도 참 / 거짓의인가 __new__()__del__()?

편집 : 매우 유사한 질문이 있습니다 : 파이썬의 상속과 재정 __init__



답변

파이썬에서 슈퍼 클래스를 호출하는 __init__것은 선택 사항입니다. 호출하면 super식별자 사용 여부 또는 수퍼 클래스 이름을 명시 적으로 지정할지 여부도 선택 사항입니다 .

object.__init__(self)

객체의 경우, super 메소드가 비어 있으므로 super 메소드를 호출 할 필요는 없습니다. 동일합니다 __del__.

반면에, for __new__는 실제로 다른 메소드를 명시 적으로 리턴하지 않는 한 실제로 super 메소드를 호출하고 해당 리턴을 새로 작성된 오브젝트로 사용해야합니다.


답변

__init__현재 클래스에서 수행되는 작업 외에도 수퍼에서 수행 해야 할 작업이 필요한 경우 __init__,자동으로 수행되지 않으므로 직접 호출해야합니다. 그러나 super에서 아무것도 필요하지 않으면 __init__,전화 할 필요가 없습니다. 예:

>>> class C(object):
        def __init__(self):
            self.b = 1


>>> class D(C):
        def __init__(self):
            super().__init__() # in Python 2 use super(D, self).__init__()
            self.a = 1


>>> class E(C):
        def __init__(self):
            self.a = 1


>>> d = D()
>>> d.a
1
>>> d.b  # This works because of the call to super's init
1
>>> e = E()
>>> e.a
1
>>> e.b  # This is going to fail since nothing in E initializes b...
Traceback (most recent call last):
  File "<pyshell#70>", line 1, in <module>
    e.b  # This is going to fail since nothing in E initializes b...
AttributeError: 'E' object has no attribute 'b'

__del__같은 방법입니다 (그러나 __del__마무리 에 의존하는 것에주의하십시오 -대신 with 문을 통해 수행하는 것을 고려하십시오).

나는 거의 __new__. 모든 초기화를 사용 하지 않는다 .__init__.


답변

Anon의 답변에서 :
__init__현재 수업에서 수행되고있는 것 외에 수퍼로부터 무언가를해야한다면 __init__, 자동으로 일어나지 않기 때문에 직접 호출해야합니다.”

그는 믿어지지 않습니다 : 그는 상속의 원칙과 정확히 반대되는 말을하고 있습니다.

그것은 것이 아니다 “슈퍼의에서 뭔가 __init__ (…) 자동으로 일어나지 않을 것입니다” 기본 클래스 ‘가 있기 때문에 자동으로 일어날 것입니다,하지만 일이 발생하지 __init__파생-제공자 라이선스 계약의 정의에 의해 오버라이드 (override)한다__init__

그러면 파생 된 클래스를 정의하는 이유 __init__는 누군가가 상속에 의존 할 때 목표를 무시하기 때문입니다.

그것은 기본 클래스에서 수행되지 않은 것을 정의해야하기 때문이며 __init__, 그것을 얻을 수있는 유일한 가능성은 실행을 파생 클래스의 __init__함수 에 넣는 것입니다.
다시 말해, 이 클래스__init____init__ 가 재정의되지 않은 경우 기본 클래스 에서 자동으로 수행되는 것 외에도 기본 클래스에 무언가가 필요합니다 .
반대가 아닙니다.

그러면 문제는 기본 클래스에있는 원하는 명령 __init__이 인스턴스화 시점에 더 이상 활성화되지 않는다는 것입니다. 이 비활성화를 상쇄하기 위해서는 특별한 것이 필요하다 :베이스 클래스에 의해 수행되는 초기화를 추가하지 말고 유지__init__ 하기 위해 베이스 클래스를 명시 적으로 호출한다 . 그것이 공식 문서에서 정확히 말한 것입니다.__init__

파생 클래스의 재정의 메서드는 실제로 같은 이름 의 기본 클래스 메서드단순히 대체하기보다는 확장하는 것이 좋습니다 . 기본 클래스 메소드를 직접 호출하는 간단한 방법이 있습니다. BaseClassName.methodname (self, arguments)을 호출하십시오.
http://docs.python.org/tutorial/classes.html#inheritance

그게 다 이야기입니다 :

  • 목표가 기본 클래스에 의해 수행되는 초기화를 유지하는 것, 즉 순수한 상속, 특별한 것은 필요하지 않으며 __init__파생 클래스에서 함수 를 정의하지 않아야합니다.

  • 목표가 기본 클래스에 의해 수행 된 초기화를 대체하는 __init__경우 파생 클래스에 정의되어야합니다.

  • 기본 클래스에 의해 수행 된 초기화에 프로세스를 추가하는 것이 목표 인 경우, 기본 클래스에 __init__ 대한 명시 적 호출을 포함하여 파생 클래스를 정의해야합니다.__init__

Anon의 포스트에서 놀랍게 생각하는 것은 그가 상속 이론의 반대를 표현할뿐만 아니라 머리카락을 돌리지 않고 upvoted하는 5 명의 사람들이 지나갔으며, 2 년 안에 아무도 반응하지 않았다는 것입니다. 흥미로운 주제를 비교적 자주 읽어야하는 스레드


답변

편집 : (코드 변경 후)
부모님 __init__(또는 다른 기능) 을 호출 해야하는지 여부를 알려주는 방법은 없습니다 . 상속은 분명히 그러한 요청없이 작동합니다. 그것은 모두 코드의 논리에 달려 있습니다. 예를 들어, 모든 __init__것이 부모 클래스에서 끝나면 자식 클래스를 __init__모두 건너 뛸 수 있습니다 .

다음 예제를 고려하십시오.

>>> class A:
    def __init__(self, val):
        self.a = val


>>> class B(A):
    pass

>>> class C(A):
    def __init__(self, val):
        A.__init__(self, val)
        self.a += val


>>> A(4).a
4
>>> B(5).a
5
>>> C(6).a
12


답변

어렵고 빠른 규칙은 없습니다. 클래스 문서는 서브 클래스가 수퍼 클래스 메소드를 호출해야하는지 여부를 표시해야합니다. 때로는 수퍼 클래스 동작을 완전히 바꾸고 다른 경우에는 수퍼 클래스 호출 전후에 자신의 코드를 호출해야합니다.

업데이트 : 동일한 기본 로직이 모든 메소드 호출에 적용됩니다. 생성자는 병렬 생성자 (예 : 데이터베이스 할당과 같은 자원 할당)와 같이 특수한 고려 사항 (동작을 결정하는 상태를 설정하는 경우가 많음)과 소멸자를 고려해야합니다. 그러나 render()위젯 의 방법 에도 동일하게 적용될 수 있습니다 .

추가 업데이트 : OPP 란 무엇입니까? 당신은 OOP를 의미합니까? 아니오-서브 클래스는 종종 수퍼 클래스 디자인에 대해 알아야 합니다 . 내부 구현 세부 사항이 아니라 슈퍼 클래스가 클라이언트와 맺은 기본 계약 (클래스 사용). 이것은 어떠한 방식으로도 OOP 원칙을 위반하지 않습니다. 그렇기 때문에 protected일반적으로 OOP에서 유효한 개념입니다 (물론 파이썬에서는 그렇지 않습니다).


답변

IMO, 전화해야합니다. 수퍼 클래스가 object인 경우 , 그렇지 않아야하지만 다른 경우에는 호출하지 않는 것이 예외적이라고 생각합니다. 이미 다른 사람들이 대답했듯이 클래스가 __init__초기화 할 (추가) 내부 상태가없는 경우와 같이 클래스를 재정의 할 필요가없는 경우 매우 편리합니다 .


답변

그렇습니다 __init__. 좋은 코딩 연습으로 항상 기본 클래스를 명시 적으로 호출해야합니다 . 잊어 버리면 미묘한 문제 나 런타임 오류가 발생할 수 있습니다. __init__매개 변수를 사용하지 않더라도 마찬가지 입니다. 이것은 컴파일러가 암시 적으로 기본 클래스 생성자를 호출하는 다른 언어와 다릅니다. 파이썬은 그렇게하지 않습니다!

항상 기본 클래스를 호출하는 주된 이유 _init__는 기본 클래스가 일반적으로 멤버 변수를 작성하여 기본값으로 초기화 할 수 있기 때문입니다. 따라서 기본 클래스 init를 호출하지 않으면 해당 코드 중 어느 것도 실행되지 않으며 멤버 변수가없는 기본 클래스로 끝납니다.

:

class Base:
  def __init__(self):
    print('base init')

class Derived1(Base):
  def __init__(self):
    print('derived1 init')

class Derived2(Base):
  def __init__(self):
    super(Derived2, self).__init__()
    print('derived2 init')

print('Creating Derived1...')
d1 = Derived1()
print('Creating Derived2...')
d2 = Derived2()

인쇄합니다 ..

Creating Derived1...
derived1 init
Creating Derived2...
base init
derived2 init

이 코드를 실행하십시오 .