본문 바로가기
Python/Study

[Super] 상속에 사용하는 Super 함수 알아보기

by beeny-ds 2022. 8. 3.

들어가는 글

 지난 포스팅에서는 상속(Inheritance)과 오버라이딩(Overriding)에 대해 알아봤었다. 관련된 링크는 아래 글을 참고하길 바란다.
 본 포스팅에서는 객체 지향형 프로그램 언어에서 상속 시 많이 사용하는 Super 함수에 대해 알아보도록 하자.

https://beeny-ds.tistory.com/23

 

[Overriding] 오버라이딩을 이용한 코드 수정

들어가는 글  Python 패키지를 사용하다보면 본인이 원하는 방식으로 class를 수정하고 싶을 때가 있다. 보통 pypi에서 직접 패키지를 수정하지만 git으로 내 패키지를 관리 한다면 dependency가 있는

beeny-ds.tistory.com


 

Super 함수

Super 명령어는 상속 관계에서 상속의 대상인 부모 class를 호출하는 함수이다.
super().__init__() 이라는 코드가 부모 class의 속성 및 메소드를 자동으로 불러와 해당 class에서도 사용이 가능하도록 해준다.

super(하위 class, self).__init__(arguments)

위와 같이 super() 괄호 안에 아무것도 넣어주지 않아도 된다.(단, python 3.x version 의 경우만..)
.__init__() 괄호 안에는 부모 class 의 arguments 를 전부 넣어줘야 한다.

super 함수는 __init__ 메소드 뿐만 아니라 다른 메소드도 호출하여 사용할 수 있다.
만약 def who_name(self): 이라는 메소드가 있다면 super().who_name() 으로 호출하여 사용하면 된다.

예시를 통해 super().__init__() 을 자세히 살펴보자.
class Super_cl:    # 부모 class 지정
    def __init__(self, name: str, kick_name: str):
        self.name = name
        self.kick_name = kick_name
        
        info = f"{name}'s kick name is {kick_name}"
        print(info)
        self.info = info
        
    def age(self, age):
        print(f"{self.name}'s' age is {age}")
        
    def like_food(self, food):
        print(f"{self.name} likes {food}")
        print(f"{self.name}'s info: \n name: {self.kick_name} \n favorit food: {food}")
        

class Sub_cl(Super_cl):    # 자식 class 지정
    def __init__(self, name, kick_name):
        super(Sub_cl, self).__init__(name, kick_name)
        # super().__init__(name, kick_name)    이것도 가능
    
    def like_food(self, food, drink):    # 부모 class 메소드 구조 변경
        print(f"{self.name} likes {food} and {drink}")
        print(self.info)
        
        
parent = Super_cl(name = 'Beeny', kick_name = 'talent')
parent.age(age = 100)
parent.like_food(food = '국밥')

chid = Sub_cl(name = 'Beeny', kick_name = 'talent')
chid.age(age = 100)
chid.like_food(food = '순대국', drink = '이온 음료')

출력 결과는 아래와 같이 나온다.

더보기

>>> Beeny's kick name is talent
>>> Beeny's' age is 100
>>> Beeny likes 국밥
>>> Beeny's info: 
        name: talent
        favorit food: 국밥

>>> Beeny's kick name is talent
>>> Beeny's' age is 100
>>> Beeny likes 순대국 and 이온 음료
>>> Beeny's kick name is talent

 

부모 class 의 __init__ 메소드에서 만들어준 'info' 가 자식 class 에서도 'print' 된 것을 볼 수 있다. 
자식 class 에서 오버라이딩을 통해 like_food 메소드를 다르게 정의해줬지만 super 함수로 인해 'self.info' 를 like_food 메소드에서 사용해준 것을 볼 수 있다. 만약 super().__init__() 을 사용하지 않았다면 자식 class 의 like_food 메소드에서는 'self.info' 를 사용할 수 없다. 부모 class 의 __init__ 메소드에서 정의한 'self.info' 정보를 가져올 수 없기 때문이다.

그렇다면 super 함수를 사용할 때 주의할 점은 무엇일까?


 

Super 함수 사용 시 주의할 점

Super 함수를 사용하며 필자가 경험한 실수를 공유하고자 한다. 

  • super().__init__() 의 괄호 안 부모 class 의 arguments 를 지정할 때 default 값은 설정하지 말도록 하자. (설정한 default 값이 부모 class 의 __init__ 메소드에서 연산된다.)
  • 자식 class 에서 __init__ 메소드를 만들 때 부모 class 의 __init__ 메소드에 해당하는 arguments 값들을 지정해야 한다. (만약 지정하지 않으면 인자가 없다는 에러를 만난다.)

필자가 코딩하는 방식은 아래와 같다.

class Super_cl:    # 부모 class 지정
    def __init__(self, 
                 name: str,
                 kick_name: str):
        self.name = name
        self.kick_name = kick_name
        
        info = f"{name}'s kick name is {kick_name}"
        print(info)
        self.info = info
        
    def age(self, age):
        print(f"{self.name}'s' age is {age}")
        
    def like_food(self, food):
        print(f"{self.name} likes {food}")
        print(f"{self.name}'s info: \n name: {self.kick_name} \n favorit food: {food}")
        

class Sub_cl(Super_cl):    # 자식 class 지정
    def __init__(self, 
                 name: str,          # 부모 class의 인자와 같은 형태로 통일 
                 kick_name: str):    # 부모 class의 인자와 같은 형태로 통일
        super(Sub_cl, self).__init__(name = name,              # 자식 class의 인자를 받도록 설정
                                     kick_name = kick_name)    # 자식 class의 인자를 받도록 설정
    
    def like_food(self, food, drink):    # 부모 class 메소드 구조 변경
        print(f"{self.name} likes {food} and {drink}")
        print(self.info)

자식 class 의 __init__ 메서드에 들어가는 인자는 부모 class 의 __init__ 메서드와 완전 통일시킨다.
super().__init__() 함수 안에 들어가는 인자는 어떤 값이 들어가는지 명시한다.

필자가 위와 같은 방식으로 개발하는 이유는 시간이 지나 예전에 개발하던 코드를 잊어버리고 다시 확인할 때를 위해서이다. 개발을 하다보면 이런 일이 생각보다 많은데 위와 같은 방식으로 구성해야 다시 코드를 확인할 때 편하기 때문이다. 물론 필자의 방식이 좋은 방식이다 라고 말하기엔 애매하다. PEP8 과 같은 규칙에 맞춰 개발하는 방법이 best다.


 

마무리 글

super 함수는 사용하기에 따라 유용할 수도 있고 오히려 불편할 수도 있다. 상속하고자 하는 class를 얼마나 이해했는지, 내부 기능(ex. 메소드)에 대해 얼마나 알고 있는지에 따라 효율성이 다르다고 생각한다. 때문에 개발을 하기 전 나의 코드를 어떻게 구성할지 명확히 설계한 뒤 시작하길 바란다.

반응형

댓글