본문 바로가기

Python

클래스 다중상속 및 @classmethod

출처 : http://egloos.zum.com/mcchae/v/11031012

코딩할때 쉽게 찾아보려고 퍼왔습니다


C++, C#, Java 등등의 OO 언어 마다 클래스 상속 개념은 다 있지만,

다중 상속은 되는 언어도 있고 안되는 언어도 있습니다.
(C++은 다중상속은 안되고 friend 개념이 들어있는 것으로 기억하는데
 사용한지 십년도 더 된거 같아 이제는 기억이 가물 가물 하네요)

암튼 파이썬에서도 다중 상속이 잘 됩니다.

class A():
def m(self, *args, **kwargs):
print '%s.m(%s,%s)' % (self.__class__.__name__, args, kwargs)
def mA(self, *args, **kwargs):
print '%s.mA(%s,%s)' % (self.__class__.__name__, args, kwargs)
class B():
def m(self, *args, **kwargs):
print '%s.m(%s,%s)' % (self.__class__.__name__, args, kwargs)
def mB(self, *args, **kwargs):
print '%s.mB(%s,%s)' % (self.__class__.__name__, args, kwargs)
class C(A,B):
def m(self, *args, **kwargs):
print '%s.m(%s,%s)' % (self.__class__.__name__, args, kwargs)

C 클래스는 A와 C 모두에서 상속을 받았고,
m 메소드는 오버로딩 되어 있습니다. 
(파이썬에서는 기냥 namespace 개념으로 해당 공간의 dict를 덮어쓰고
 참조하는 식으로 되어 있습니다)

이제 다음과 같이,

c=C()
c.m(5,6,kw='fgh')
c.mA(5,6,kw='fhi')
c.mB(5,6,kw='hij')

호출을 해 보면,

C.m((5, 6),{'kw': 'fgh'})
C.mA((5, 6),{'kw': 'fhi'})
C.mB((5, 6),{'kw': 'hij'})

와 같이 m은 C 자체 클래스의 메소드가,
또한 mA 메소드는 상속받은 A클래스,
mB 메소드는 상속받은 B클래스의 것이 호출됩니다.

이제는 @staticmethod와 @classmethod의 차이를 살펴보겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class A():
    S_VAL=1
    def m(self, *args, **kwargs):
        print '%s.m(%s,%s)' % (self.__class__.__name__, args, kwargs)
    def mA(self, *args, **kwargs):
        print '%s.mA(%s,%s)' % (self.__class__.__name__, args, kwargs)
    @staticmethod
    def s():
        print '%s.c: S_VAL=%s' % (A.__name__, A.S_VAL)
    @classmethod
    def c(cls):
        print '%s.c: S_VAL=%s' % (cls.__name__, cls.S_VAL)
class B():
    S_VAL=2
    def m(self, *args, **kwargs):
        print '%s.m(%s,%s)' % (self.__class__.__name__, args, kwargs)
    def mB(self, *args, **kwargs):
        print '%s.mB(%s,%s)' % (self.__class__.__name__, args, kwargs)
class C(A,B):
    S_VAL=3
    def m(self, *args, **kwargs):
        print '%s.m(%s,%s)' % (self.__class__.__name__, args, kwargs)
cs

위와 같이 되어 있는 A클래스에서 s() 라는 @static method가 있습니다.
이것은 첫번째 인자가 self로 시작하는 일반 메소드와는 달리 self로 시작하지 않습니다.
그리고 내용으로는 클래스에 정의되어 있는 S_VAL을 출력합니다.

일반적인 클래스 method라 생각하면 됩니다.

따라서, 

A.s()
C.s()

라고 호출하면,

A.c: S_VAL=1
A.c: S_VAL=1

라고 동일 결과가 나옵니다.

상속은 받았지만 실질적으로 동일 함수가 수행되는 것이지요.

자 이제는 A클래서의 c라는 classmethod를 살펴보겠습니다.
@classmethod 라는 데코레이터를 이용하고,
첫번째 인자로는 cls를 받습니다.
그리고 내용으로는 클래스에 정의되어 있는 S_VAL을 출력합니다.

A.c()
C.c()

라고 호출하면,

A.c: S_VAL=1
C.c: S_VAL=3

라는 결과가 잘 나옵니다.

즉 상속한 클래스의 클래스 내용에 따라 작업을 하고 싶으면 @classmethod를 이용하고,
아무것도 없이 클래스 함수만을 이용한다면 @staticmethod를 호출하는 것이지요...

이것을 어저께야 제대로 이용을 하고는,
'왜 바보같이 이제서야 알았을까나... 그래도 이제야 제대로 알았으니 다행이다'
라고 생각하였답니다.


어느분께는 도움이 되셨기를....