Python: @classmethod

이걸 뭐에 어떻게 쓰는지는 아직 잘 모르겠다.
programiz.com 을 참고하여 늘 그렇듯 간단하게만 정리해본다.


소스는 위 페이지에서 가져왔다.

from datetime import date


class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    @classmethod
    def fromBirth(cls, name, birthYear):
        return cls(name, date.today().year - birthYear)

    def display(self):
        print(self.name + "'s age is: " + str(self.age))


class NewPerson:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    @staticmethod
    def fromFathersAge(name, fatherAge, fatherPersonAgeDiff):
        return NewPerson(name, date.today().year - fatherAge + fatherPersonAgeDiff)

    @classmethod
    def fromBirth(cls, name, birthYear):
        return cls(name, date.today().year - birthYear)

    def display(self):
        print(self.name + "'s age is: " + str(self.age))


class Man(NewPerson):
    sex = 'Male'

classmethod 를 정의하는 방법도 두가지다. 허나, 데코레이터를 사용하는 방식(@classmethod)만을 정리하기로 한다. 다른 방법은 위 글에 나와있다. 위에 staticmethod 도 같이 나와있다.

classmethod 를 정의할 때는 @classmethod 라고 쓰고, 바로 아래에 함수(def)를 정의한다.
그리고! 가장 중요한 점!
일반 클래스에서 메소드는 self 인수를 갖지만, classmethod 는 cls 라는 인수가 필수다. 물론, self 도 마찬가지지만, 반드시 cls 를 사용해야한다는 법은 없다. 어떤 단어를 써도 되지만, ‘소통’을 위해서 보통 self, cls 등을 쓴다.

staticmethod 는 일반 함수/메소드와 유사하게 사용하므로, self, cls, obj 등의 인수는 불필요하다.

사용법은, 클래스명.메소드() 형식도 되고, 심지어 인스턴스.메소드() 도 된다.

# classmethod
myMan = Man.fromBirth('홍길동', 1967)
yourMan = myMan.fromBirth('전우치', 1980)

# staticmethod
herMan = Man.fromFathersAge('서경덕', 1965, 20)

isinstance(myMan, Man)
True

isinstance(yourMan, Man)
True

isinstance(herMan, Man)
False

isinstance(herMan, NewPerson)
True

하지만, 기본 사용법은 class.method() 쪽이 맞는 듯?

이런 식으로 새로운 인스턴스를 만드는 방식을 Factory Method 라고 한다고 하는데.. C++ 등 다른 언어에선 꼭 알아야 하는 모양이다. Python 에선..?? 잘 모르겠다.

myMan 과 yourMan 은 어쨌든 classmethod 를 사용했다. 여기선 cls(name, date.today().year - birthYear) 를 return 했는데, cls 는 클래스를 뜻하고, 보다 정확하게는 이 메소드가 속해있는 NewPerson 이 된다. 단! Man 은 NewPerson 을 상속했고, Man.fromBirth() 로 실행했으므로, 여기서 클래스는 Man 이 된다.

위의 결과를 보면 myMan, yourMan 이 모두 Man 에 속해있음을 볼 수 있다. 물론, NewPerson 의 인스턴스이기도 하다.
그런데, herMan 은 좀 다르다. 여기선 staticmethod 를 사용했고, return 값이 NewPerson(name, date.today().year – fatherAge + fatherPersonAgeDiff) 으로 명시되어(hardcoded) 있으므로, Man.fromFathersAge() 로 실행했지만 Man 소속이 아닌 NewPerson 에게만 귀속되는 상황이 돼 버렸다.

따라서, 상속 시에 인스턴스를 제대로 만들기 위해서 classmethod 를 쓴다고 한다.

오늘은 여기까지.

아무도안아무도안
Author: 아무도안

안녕하세요. 글 남겨주셔서 고맙습니다.