development

왜 슈퍼 클래스 __init__ 메소드가 자동으로 호출되지 않습니까?

big-blog 2020. 6. 18. 07:24
반응형

왜 슈퍼 클래스 __init__ 메소드가 자동으로 호출되지 않습니까?


파이썬 디자이너들은 왜 다른 언어에서와 같이 서브 클래스의 __init__()메소드가 자동으로 __init__()슈퍼 클래스 메소드를 호출하지 않기로 결정 했습니까? 파이썬과 추천 관용구는 실제로 다음과 같은가?

class Superclass(object):
    def __init__(self):
        print 'Do something'

class Subclass(Superclass):
    def __init__(self):
        super(Subclass, self).__init__()
        print 'Do something else'

파이썬의 사이의 중요한 차이 __init__와 그 다른 언어 생성자__init__입니다 하지 그것이이다 : 생성자 초기화 (실제 생성자를 참조 나중에 ;-)입니다 (있는 경우 만 __new__) 및 작동 완전히 다르게 다시. 반면 건설 의 모든 슈퍼 클래스를 (당신이 아래로 건설 계속 "전에"의심의 여지가 이렇게) 분명히 당신이있어 말의 일부 구성하는 서브 클래스의 인스턴스를, 그 명확의 경우에는 해당되지 않습니다 초기화수퍼 클래스의 초기화를 건너 뛰고, 변경하고, 제어해야하는 많은 사용 사례가 있기 때문에, 서브 클래스 초기화의 "중간"등에서 발생합니다.

기본적으로 이니셜 라이저의 슈퍼 클래스 위임은 파이썬에서 자동으로 동일하지 않기 때문에 이와 같은 위임은 다른 방법 에서도 자동으로 수행되지 않습니다. 이러한 "다른 언어"는 자동 슈퍼 클래스 위임을 수행하지 않습니다. 중 ... 다른 방법 단지 내가 언급 한 바와 같이, (해당, 소멸자 및 경우), 생성자에 대한은 하지 파이썬의 무엇 __init__이다. (의 행동은 __new__실제로 당신의 질문과 직접적으로 관련이 없지만, 매우 독특합니다. 왜냐하면 __new__실제로 무언가를 만들 필요가없는 독특한 생성자이므로 기존 인스턴스 또는 비 인스턴스를 완벽하게 반환 할 수 있습니다. ... 분명히 파이썬은 당신에게 많은 것을 제공합니다당신이 생각하는 "다른 언어들"보다 더 많은 역학을 제어 할 수 있으며, 여기 에는 자동 위임이없는 것도 포함 __new__됩니다!-).


사람들이 "파이썬 (Zen of Python)"을 앵무새로 삼을 때 다소 당황 스럽습니다. 디자인 철학이다. 특정 디자인 결정은 항상 보다 구체적인 용어로 설명 될 수 있으며, 그렇지 않으면 "파이썬 (Zen of Python)"이 무엇인가를위한 변명이되어야합니다.

이유는 간단합니다. 기본 클래스를 구성하는 방법과 전혀 유사한 방식으로 파생 클래스를 구성 할 필요는 없습니다. 더 많은 매개 변수를 가질 수 있고, 더 적은 수의 매개 변수가 다른 순서로 있거나 전혀 관련되지 않을 수 있습니다.

class myFile(object):
    def __init__(self, filename, mode):
        self.f = open(filename, mode)
class readFile(myFile):
    def __init__(self, filename):
        super(readFile, self).__init__(filename, "r")
class tempFile(myFile):
    def __init__(self, mode):
        super(tempFile, self).__init__("/tmp/file", mode)
class wordsFile(myFile):
    def __init__(self, language):
        super(wordsFile, self).__init__("/usr/share/dict/%s" % language, "r")

이것은뿐만 아니라 모든 파생 된 방법에 적용됩니다 __init__.


Java 및 C ++ 에서는 메모리 레이아웃으로 인해 기본 클래스 생성자가 호출되어야합니다.

당신은 클래스가있는 경우 BaseClass멤버를 field1, 당신은 새로운 클래스 생성 SubClass멤버 추가 field2의 다음 인스턴스 SubClass을위한 공간을 포함 field1하고를 field2. 상속하는 모든 클래스가 자체 생성자에서 초기화 를 반복하도록 요구하지 않는 한 BaseClass을 채우려면 생성자가 field1필요합니다 BaseClass. 그리고 field1비공개 인 경우 상속 클래스 초기화 할 수 없습니다field1 .

파이썬은 자바 나 C ++이 아닙니다. 모든 사용자 정의 클래스의 모든 인스턴스는 동일한 '모양'을 갖습니다. 기본적으로 속성을 삽입 할 수있는 사전입니다. 초기화가 완료되기 전에 모든 사용자 정의 클래스의 모든 인스턴스는 거의 동일합니다 . 아직 저장하지 않은 속성을 저장하는 장소 일뿐입니다.

따라서 파이썬 서브 클래스는 기본 클래스 생성자를 호출하지 않는 것이 좋습니다. 원하는 경우 속성 자체를 추가 할 수 있습니다. 계층 구조의 각 클래스에 대해 지정된 수의 필드에 예약 된 공간이 없으며 BaseClass메서드 에서 코드로 추가 된 특성과 메서드 에서 코드로 추가 된 특성간에 차이가 없습니다 SubClass.

일반적인 경우처럼 SubClass실제로 BaseClass자신의 사용자 정의를 수행하기 전에 모든 불변 값을 설정하려는 경우 전화를 걸 수 있습니다 BaseClass.__init__()(또는 사용 super하지만 복잡하고 때로는 자체 문제가 있습니다). 그러나 당신은 할 필요가 없습니다. 그리고 당신은 그것을 전후에, 또는 다른 주장으로 할 수 있습니다. 당신이 원한다면 지옥 BaseClass.__init__보다 다른 방법으로 from을 호출 할 수 있습니다 __init__. 어쩌면 당신은 기괴한 게으른 초기화 일이있을 수 있습니다.

파이썬은 일을 단순하게 유지함으로써 이러한 유연성을 달성합니다. __init__속성을 설정 하는 메소드를 작성하여 객체를 초기화합니다 self. 그게 다야. 정확히 메서드이기 때문에 메서드와 똑같이 동작합니다. 먼저해야 할 일이나 다른 일을하지 않으면 자동으로 일어날 일에 관한 이상하고 직관적이지 않은 규칙은 없습니다. 그것이 제공 해야하는 유일한 목적은 객체 초기화 중에 초기 속성 값을 설정하기 위해 실행하는 후크입니다. 다른 것을 원한다면 코드에 명시 적으로 작성하십시오.


"명시적인 것이 묵시적인 것보다 낫다." 'self'를 명시 적으로 작성해야 함을 나타내는 동일한 이유입니다.

I think in in the end it is a benefit-- can you recite all of the rules Java has regarding calling superclasses' constructors?


Often the subclass has extra parameters which can't be passed to the superclass.


Right now, we have a rather long page describing the method resolution order in case of multiple inheritance: http://www.python.org/download/releases/2.3/mro/

If constructors were called automatically, you'd need another page of at least the same length explaining the order of that happening. That would be hell...


To avoid confusion it is useful to know that you can invoke the base_class __init__() method if the child_class does not have an __init__() class.

Example:

class parent:
  def __init__(self, a=1, b=0):
    self.a = a
    self.b = b

class child(parent):
  def me(self):
    pass

p = child(5, 4)
q = child(7)
z= child()

print p.a # prints 5
print q.b # prints 0
print z.a # prints 1

In fact the MRO in python will look for __init__() in the parent class when can not find it in the children class. You need to invoke the parent class constructor directly if you have already an __init__() method in the children class.

For example the following code will return an error: class parent: def init(self, a=1, b=0): self.a = a self.b = b

    class child(parent):
      def __init__(self):
        pass
      def me(self):
        pass

    p = child(5, 4) # Error: constructor gets one argument 3 is provided.
    q = child(7)  # Error: constructor gets one argument 2 is provided.

    z= child()
    print z.a # Error: No attribute named as a can be found.

Maybe __init__ is the method that the subclass needs to override. Sometimes subclasses need the parent's function to run before they add class-specific code, and other times they need to set up instance variables before calling the parent's function. Since there's no way Python could possibly know when it would be most appropriate to call those functions, it shouldn't guess.

If those don't sway you, consider that __init__ is Just Another Function. If the function in question were dostuff instead, would you still want Python to automatically call the corresponding function in the parent class?


i believe the one very important consideration here is that with an automatic call to super.__init__(), you proscribe, by design, when that initialization method is called, and with what arguments. eschewing automatically calling it, and requiring the programmer to explicitly do that call, entails a lot of flexibility.

after all, just because class B is derived from class A does not mean A.__init__() can or should be called with the same arguments as B.__init__(). making the call explicit means a programmer can have e.g. define B.__init__() with completely different parameters, do some computation with that data, call A.__init__() with arguments as appropriate for that method, and then do some postprocessing. this kind of flexibility would be awkward to attain if A.__init__() would be called from B.__init__() implicitly, either before B.__init__() executes or right after it.

참고URL : https://stackoverflow.com/questions/3782827/why-arent-superclass-init-methods-automatically-invoked

반응형