itsource

__init__() 메서드를 사용한 Python super()에 대해

mycopycode 2022. 9. 23. 00:16
반응형

__init__() 메서드를 사용한 Python super()에 대해

?는 왜?super()

를 사용하는 것에 차이가 있습니까?Base.__init__ ★★★★★★★★★★★★★★★★★」super().__init__

class Base(object):
    def __init__(self):
        print "Base created"
        
class ChildA(Base):
    def __init__(self):
        Base.__init__(self)
        
class ChildB(Base):
    def __init__(self):
        super(ChildB, self).__init__()
        
ChildA() 
ChildB()

super()를 사용하면 베이스 클래스를 명시적으로 참조하지 않아도 됩니다.이것은 좋은 방법입니다.하지만 가장 큰 장점은 여러 번 상속을 받는 것입니다. 여기서 온갖 재미있는 일이 일어날 수 있습니다.Super에 관한 표준 문서를 참조해 주십시오.

Python 3.0에서는 구문이 변경된 것에 주의해 주십시오.super().__init__()super(ChildB, self).__init__()IMO가 좀 더 좋은 것 같아요.또, 표준 문서에서는, 사용의 가이드도 참조하고 있습니다.

난 이해하려고 노력중이야super()

「 」를 사용하는 super공동 다중 상속을 사용할 수 있는 자녀 클래스가 Method Resolution Order(MRO; 메서드 해결 순서)에서 올바른 다음 부모 클래스 함수를 호출하는 것입니다.

Python 3 에서는, 다음과 같이 말할 수 있습니다.

class ChildB(Base):
    def __init__(self):
        super().__init__()

에서는 Python 2를 호출해야 .super정의 및 "Defining class name"과 "Defining class name"을 사용하여 합니다.self그러나 앞으로는 중복되고 (이름 검색 때문에) 속도가 느리고 상세하기 때문에 피하겠습니다(아직 Python을 업데이트하지 않았다면 업데이트하십시오).

        super(ChildB, self).__init__()

슈퍼가 없으면 다음 부모 콜을 유선 연결하기 때문에 여러 상속을 사용할 수 있는 기능이 제한됩니다.

        Base.__init__(self) # Avoid this.

아래에 자세히 설명하겠습니다.

"이 코드에는 실제로 어떤 차이가 있습니까?:"

class ChildA(Base):
    def __init__(self):
        Base.__init__(self)

class ChildB(Base):
    def __init__(self):
        super().__init__()

은 '다르다'에 .ChildB 때문에, 간접의 이 생깁니다.__init__super하여 다음, 、 , 、 음 、 음 、 음 、 , 、 , 、 , , , , , 。__init__MRO m m m m 。

의존성 주입과 공동 다중 상속을 보여주는 표준 질문인 'Python에서 '슈퍼'를 사용하는 방법'의 답변에서 이 차이를 설명합니다.

Python이 없는 super

실제로 비슷한 super(C에서 구현되는 방법, 체크 동작과 폴백 동작을 제외하고 Python으로 변환됩니다).

class ChildB(Base):
    def __init__(self):
        mro = type(self).mro()
        check_next = mro.index(ChildB) + 1 # next after *this* class.
        while check_next < len(mro):
            next_class = mro[check_next]
            if '__init__' in next_class.__dict__:
                next_class.__init__(self)
                break
            check_next += 1

네이티브 Python과 조금 더 비슷하게 작성:

class ChildB(Base):
    def __init__(self):
        mro = type(self).mro()
        for next_class in mro[mro.index(ChildB) + 1:]: # slice to end
            if hasattr(next_class, '__init__'):
                next_class.__init__(self)
                break

'아예'가 super오브젝트, 방법 해결 순서에서 적절한 다음 메서드를 호출할 수 있도록 이 매뉴얼 코드를 모든 곳에 작성(또는 다시 작성!)야야합합합합합

어떻게 슈퍼가 Python 3에서 호출된 메서드에서 어떤 클래스와 인스턴스를 명시적으로 알리지 않고 이 작업을 수행할 수 있을까요?

변수로서 되어 있다)를합니다.__class__(클래스에 대한 콜함수가 닫힘) 및 해당 함수의 첫 번째 인수는 사용하는 Method Resolution Order(MRO; 메서드 해결 순서)를 알려주는 인스턴스 또는 클래스여야 합니다.

MRO의 첫 번째 인수가 필요하기 때문에 스태틱메서드를 사용하는 것은 불가능합니다.이는 발신원 클래스의 MRO에 액세스할없기 때문입니다.

기타 답변에 대한 비판:

super()를 사용하면 베이스 클래스를 명시적으로 참조하는 것을 피할 수 있습니다.이것은 좋은 일이기도 합니다.그러나 주요 장점은 여러 가지 상속이 있기 때문에 모든 종류의 재미있는 일이 일어날 수 있습니다.Super에 관한 표준 문서를 참조해 주십시오.

알 수, 은.super부모 클래스의 기입을 회피하는 것은 아닙니다.여기서 중요한 것은 Method Resolution Order(MRO; 메서드 해결 순서)에서 다음 메서드가 호출되도록 하는 것입니다.이는 다중 상속에서 중요해집니다.

여기서 설명할게요.

class Base(object):
    def __init__(self):
        print("Base init'ed")

class ChildA(Base):
    def __init__(self):
        print("ChildA init'ed")
        Base.__init__(self)

class ChildB(Base):
    def __init__(self):
        print("ChildB init'ed")
        super().__init__()

그리고 Child의 이름을 따서 부를 종속성을 만듭니다.

class UserDependency(Base):
    def __init__(self):
        print("UserDependency init'ed")
        super().__init__()

이제 기억하세요.ChildB 슈퍼, 슈퍼, 슈퍼, 를 사용합니다.ChildA지지않않않않다다

class UserA(ChildA, UserDependency):
    def __init__(self):
        print("UserA init'ed")
        super().__init__()

class UserB(ChildB, UserDependency):
    def __init__(self):
        print("UserB init'ed")
        super().__init__()

★★★★★★★★★★★★★★★★★.UserA 메서드 "UserDependency" 를 호출하지 .

>>> UserA()
UserA init'ed
ChildA init'ed
Base init'ed
<__main__.UserA object at 0x0000000003403BA8>

★★★★★★★★★★★★★★★★★.UserB는 UserDependency 를 합니다.이는 UserDependency 가 를 호출하기 때문입니다.ChildBsuper:

>>> UserB()
UserB init'ed
ChildB init'ed
UserDependency init'ed
Base init'ed
<__main__.UserB object at 0x0000000003403438>

다른 답변에 대한 비판

ChildB를 서브클래스로 분류하면 반드시 오류가 발생하므로 어떤 경우에도 다음 작업을 수행하지 마십시오.

super(self.__class__, self).__init__()  # DON'T DO THIS! EVER.

(그 답변은 영리하지도 않고 특별히 흥미롭지도 않지만, 코멘트의 직접적인 비판과 17표 이상의 하향 투표에도 불구하고, 친절한 편집자가 그의 문제를 해결할 때까지 답변자는 그것을 계속 제안했습니다.)

: 사사를 사용합니다.self.__class__super()재귀로 이어집니다. super그럼 MRO에서 다음 부모(이 답변의 첫 번째 섹션 참조)에서 자녀 클래스를 검색할 수 있습니다.라고 말하면. if. if. 면. if. 면. if. if. if.super메서드를 하고 논리적인 오류 또는 논리적인 할 수 .RuntimeError★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

>>> class Polygon(object):
...     def __init__(self, id):
...         self.id = id
...
>>> class Rectangle(Polygon):
...     def __init__(self, id, width, height):
...         super(self.__class__, self).__init__(id)
...         self.shape = (width, height)
...
>>> class Square(Rectangle):
...     pass
...
>>> Square('a', 10, 10)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __init__
TypeError: __init__() missing 2 required positional arguments: 'width' and 'height'

3의 새로운 3super()인수가 없는 호출 방식은 다행히 이 문제를 회피할 수 있습니다.

Python 3.0+에서는, 다음과 같은 기능을 사용할 수 있습니다.

super().__init__()

콜을 발신합니다.이것은 간결하고 부모 OR 클래스명을 명시적으로 참조할 필요가 없기 때문에 편리합니다.2.7 2.7, Python 2.7, Python 2.7, Python 2.7, Python 2.7, Python 2.7, Python 2.7, Python 2.7, Python 2.7, Python 2.7, Python 2.7, Python 2.7, Python 2.7, Python 2.7, Python 2.7, Python 2.7, Python 2.7, Python 2.7, 2.7, 2.7,self.__class__래스이 、

super(self.__class__, self).__init__()  # DON'T DO THIS!

다만, 이것에 의해, 다음의 콜이 끊어집니다.super서 "는" )에 지정합니다.self.__class__아이 클래스를 반환할 수 있습니다.예를 들어 다음과 같습니다.

class Polygon(object):
    def __init__(self, id):
        self.id = id

class Rectangle(Polygon):
    def __init__(self, id, width, height):
        super(self.__class__, self).__init__(id)
        self.shape = (width, height)

class Square(Rectangle):
    pass

을 듣습니다.SquareRectangle에 대해 별도의 생성자를 작성하지 않을 경우Square의 이기 때문입니다.Rectangle충분하지만 어떤 이유로든 다른 방법을 다시 구현할 수 있도록 Square를 구현하고 싶습니다.

Square를 사용합니다.mSquare = Square('a', 10,10)은 의 합니다.Python은 Python의 컨스트럭터를 호출합니다.Rectangle안 줬기 Square 에서는 의 컨스트럭터에서는Rectangle콜, 。super(self.__class__,self).mSquare '시공자'를 ''라고 부릅니다Rectangle@S_C에서 설명한 바와 같이 무한 루프가 발생하는 방법입니다. 「」를 하면, 「」가 됩니다.super(...).__init__()에게 전화드립니다.Rectangle제가 논쟁을 하지 않기 때문에, 저는 실수를 하게 될 것입니다.

슈퍼는 부작용이 없다

Base = ChildB

Base()

예상대로 기능하다

Base = ChildA

Base()

무한 재귀에 빠집니다.

★★★★★★★★★★★…까지 하고 있습니다.super()버전 2.2에서 도입되었습니다.부모 중 하나가 최종적으로 상속되는 클래스에서 상속된 경우에만 호출할 수 있습니다.object(새로운 스타일의 클래스).

2.7 코드에 는 python 2.7을 계속 BaseClassName.__init__(self, args) 할 수 있는 super().

진짜 없어요. super() MRO를 사용하여 를 나타냅니다.cls.__mro__메서드를 호출합니다.에 을 발신했을 입니다.__init__라고 __init__MRO을 하고 , 더 좋은 으로 하고 있습니다super()( 「 」 、 「 ( 、 「 」

가장 큰 차이점은 이다.ChildA.__init__ 호출한다Base.__init__, 「」입니다.ChildB.__init__를 호출합니다.__init__(예상과는 다를 수 있습니다)의 조상 계통의 조상인 경우가 있습니다.

「 」를 ClassC다음과 같이 합니다.

class Mixin(Base):
  def __init__(self):
    print "Mixin stuff"
    super(Mixin, self).__init__()

class ChildC(ChildB, Mixin):  # Mixin is now between ChildB and Base
  pass

ChildC()
help(ChildC) # shows that the Method Resolution Order is ChildC->ChildB->Mixin->Base

이제이상부모가 아닙니다.ChildC, 이제super(ChildB, self) 가리키다Mixinself는 입니다.ChildC★★★★★★ 。

했습니다.MixinChildB ★★★★★★★★★★★★★★★★★」Base이 하면 '아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아.super()

때문에 여러 개의 할 수 한 경우, "다음에 상속"을 합니다.super런타임에 누가 조상이 될지 모르기 때문입니다.

Super con super post와 pycon 2015 첨부 동영상이 를 잘 설명해준다.

언급URL : https://stackoverflow.com/questions/576169/understanding-python-super-with-init-methods

반응형