Python 의 상속

language | 04 December 2017

Tags | class python object namespace inheritance

(예전에 적어두었던 글을 이제서야 올려본다)

python 의 상속에 대해 정리해보자.

강제상속 ? 자동상속?

강제상속 : 나에게 없을때, 부모클래스 namespace 로 거슬러 올라가 강제 사용

자동상속 : 내가 부모 클래스 메서드를 덮어썼지만, 부모클래스메서드를 사용하고 싶을 때 super(_class_, self).method() 로 부모메서드 호출

class Base :
    def __init__(self, name) :
        self.name = name

class Sub1(Base):
    pass

class Sub2(Base):
    def __init__(self, name, tall, age) :
        super(Sub2, self).__init__(name)
        self.tall = tall
        self.age = age

#자동상속
#s1 은 __init__ 이 없어서 Base 것을 참조한다
s1 = Sub1("jayne")
#강제상속
#s2 는 자체 __init__ 이 있어서 Base 것을 덮어쓴다. Base 것을 강제 이용하려면, super를 통해 강제상속시킬 수 있다.
s2 = Sub2("jayne",182, 22)

다중상속시 super 는 누구것을 가져오나?

class Base :
    def __init__(self, name) :
        self.name = name

class Sub1(Base):
    def __init__(self, name) :
        self.name = name

class Sub2(Base):
    def __init__(self, name, tall, age) :
        super(Sub2, self).__init__(name)
        self.tall = tall
        self.age = age



class SubSub(Sub1, Sub2):
    def __init__(self, name) :
        super(SubSub, self).__init__(name)

위처럼 코드를 만들면, super는 누구의 init 메서드를 강제상속할까.

후보는 Sub1 과 Sub2 이다.

후보1 : Sub2 의 메서드를 강제 상속하므로 인자로 name, tall, age 모두 넘겨줘야한다.

후보2 : Sub1 의 메서드를 찾다가, Base 의 init 메서드를 강제상속해오므로, name 만 넘겨주면 된다.

이 답을 알아보는 방법은 help() 함수이다.

ss = SubSub("so")
help(ss)
Help on SubSub in module __main__ object:

class SubSub(Sub1, Sub2)
 |  Method resolution order:
 |      SubSub
 |      Sub1
 |      Sub2
 |      Base
 |      builtins.object
 |  
 |  Methods defined here:
 |  
 |  __init__(self, name)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from Base:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)
 |  
 |  __weakref__
 |      list of weak references to the object (if defined)

Method resolution order 를 보면 알 있다.

SubSub 는 자신에게 메서드가 없을 때(자동상속)나 부모의 메서드를 super 로 가져올 때 (강제상속) 위의 ordering 을 따르므로

super().__init__() 을 호출 할 때에도, Sub1 에 __init__ 이 있기에 그 init 부터 가져와 사용하게 된다.

결론 : 모든것은 namespace 참조 순서에 달렸다.