super

매일 공부(ML)·2022년 7월 2일
0

이어드림

목록 보기
90/146

super로 부모 클래스를 초기화 하라

#자식 인스턴스에서 부모 클래스의  __init__ 메서드를 직접 호출
#부모 클래스 초기화
#다중 상속에 영향을 받은 클래스가 있다면 잘 작동하지 않는다>

class MyBaseClass:
    def __init__(self, value):
        self.value = value

class MyChildClass(MyBaseClass):
    def __init__(self):
        MyBaseClass.__init__(self,5)
"다중 상속으로 인해 발생하는 문제: 모든 하위 클래스에서 __init__호출의 순서가 정해짐X 이로 인해서 예측할 수 없는 방식으로 작동"""

class TimesTwo:
    def __init__(self):
        self.value *= 2

class PlusFive:
    def __init__(self):
        self.value +=5

class OneWay(MyBaseClass, TimesTwo, PlusFive):
    def __init__(self, value):
        MyBaseClass.__init__(self, value)
        TimesTwo.__init__(self)
        PlusFive.__init__(self)
#부모 클래스의 순서에 따라 초기화

foo = OneWay(5)
print('첫 번째 부모 클래스 순서에 따른 값은 (5*2) + 5 =', foo.value)

첫 번째 부모 클래스 순서에 따른 값은 (5*2) + 5 = 15

순서를 바꿔도 결과가 동일하다는 것은 부모 클래스의 나열한 순서와 부모 클래스의 생성자 호출 순서 불일치
class AnotherWay(MyBaseClass, PlusFive, TimesTwo):
    def __init__(self, value):
        MyBaseClass.__init__(self, value)
        TimesTwo.__init__(self)
        PlusFive.__init__(self)
bar = AnotherWay(5)
print('두 번째 부모 클래스 순서에 따른 값은 (5*2) + 5 =', bar.value)

두 번째 부모 클래스 순서에 따른 값은 (5*2) + 5 = 15

"""
파이썬에는 super라는 내장 함수와 표준 메서드 결정 순서(MRO)가 있다.
super를 사용하면 다이아몬드 계층의 공동 상위 크랠스르 한 번만 호출
MRO는 상위 클래스를 초기화하는 순서 정의
C3 선형화라는 알고리즘 사용

다이아몬드의 정점에 있는 MyBaseClass__init__는 단 한 번만 실행된다.
다른 부모 클래스의 생성자는 class문에 지정된 순서로 호출
"""

class TimesSevenCorrect(MyBaseClass):
    def __init__(self, value):
        super().__init__(value)
        self.value *= 7

class PlusNineCorrect(MyBaseClass):
    def __init__(self, value):
        super().__init__(value)
        self.value += 9

class GoodWay(TimesSevenCorrect, PlusNineCorrect):
    def __init__(self, value):
        super().__init__(value)
foo = GoodWay(5)
print('7*(5+9)=98이 나와야하고 실제로도', foo.value)
7*(5+9)=98이 나와야하고 실제로도 98
mro_str = '\n'.join(repr(cls) for cls in GoodWay.mro())
print(mro_str)

<class 'main.GoodWay'>
<class 'main.TimesSevenCorrect'>
<class 'main.PlusNineCorrect'>
<class 'main.MyBaseClass'>
<class 'object'>

#object 인스턴스를 초기할 때 두 파라미터를 지정할 필요가 없다.


class ExplicitTrisect(MyBaseClass):
    def __init__(self, value):
        super(ExplicitTrisect, self).__init__(value)
        self.value /= 3

class AutomaticTrisect(MyBaseClass):
    def __init__(self, value):
        super(__class__, self).__init__(value)
        self.value /=3

class ImplicitTrisect(MyBaseClass):
    def __init__(self, value):
        super().__init__(value)
        self.value /= 3

assert ExplicitTrisect(9).value ==3
assert AutomaticTrisect(9).value ==3
assert ImplicitTrisect(9).value ==3

  • 파이썬은 표준 메서드 결정 순서(MRO)를 활용해서 상위 클래스 초기화 순서와 다이아몬드 상속 문제 해결

  • 부모 클래스를 초기화할 때는 super내장 함수를 아무 인자없이 호촐하라

    • 파이썬 컴파일러가 자동으로 올바른 파라미터 넣어준다.
  • super에 파라미터 지정하는 유일한 경우

  • 자식 클래스에서 상위 클래스의 특정 기능에 접근

profile
성장을 도울 아카이빙 블로그

0개의 댓글