본문 바로가기

프로그래머/Python

[윤성우의 열혈 파이썬 중급편] 33. 클래스 메소드와 static 메소드

33. 클래스 메소드와 static 메소드

클래스 변수에 대한 이해

class Simple:
    cv = 20
    def __init__(self):
        self.iv = 10

Simple.cv   # 20
s = Simple()
s.cv        # 20
s.iv        # 20
  • 첫 대입 연산에서 생성되는 변수를 가리켜 '인스턴스 변수'라고 한다
  • 그리고 이는 각 객체별로 존재한다
    • 즉, 객체에 속한 변수이다
  • 변수를 클래스 안에도 둘 수 있다
    • 이는 '클래스 변수'가 된다
    • 클래스 변수는 클래스 이름을 통한 접근을 권한다
# count_instance.py
class Simple:
    count = 0
    def __init__(self):
        Simple.count += 1
    def get_count(self):
        return Simple.count

def main():
    s1 = Simple()
    print(s1.get_count())   # 1
    s2 = Simple()
    print(s1.get_count())   # 2
    s3 = Simple()
    print(s1.get_count())   # 3

main()

static 메소드

  • static 메소드는 클래스 변수와 상당히 유사하며, 객체에 속하지 않고 클래스에 속한다
# static_method.py
class Simple:
    def sm():
        print('static method!')
    sm = staticmethod(sm)   # sm 메소드를 static 메소드로 만드는 방법

def main():
    Simple.sm()     # static 메소드는 클래스 이름을 통해 호출 가능
    s = Simple()
    s.sm()          # static 메소드는 객체를 통해서도 호출 가능

main()
  • static 메소드는 첫 번째 인자로 self를 전달받지 않는다
  • 이는 객체가 아닌 클래스에 속한 메소드이기 때문
  • 데코레이터 방식을 권장
# count_instance2.py
class Simple:
    count = 0
    def __init__(self):
        Simple.count += 1

    @staticmethod
    def get_count():
        return Simple.count

def main():
    print(Simple.get_count())
    s = Simple()
    print(Simple.get_count())

main()

class 메소드

# class_method.py
class Simple:
    num = 5
    @staticmethod
    def sm(1):
        print('st~ 5 + {0} = {1}'.format(i, Simple.num + i))
    @classmethod
    def cm(cls, i):
        pritn('cl~ 5 + {0} = {1}'.format(i, Simple.num + i))

def main():
    Simple.sm(3)    # 클래스 이름 기반의 static 메소드 호출
    Simple.cm(3)    # 클래스 이름 기반의 class 메소드 호출
    s = Simple()
    s.sm(4)     # 객체를 대상으로 한 static 메소드 호출
    s.cm(4)     # 객체를 대상으로 한 class 메소드 호출

main()
  • class method와 static method의 외형적 차이는 첫 번째 매개변수 cls의 유무에 있다
  • 첫 번째 매개변수 cls를 빼고 보면 static 메소드와 class 메소드는 동일하다
  • cls에는 자동으로 전달되는 무엇인가가 있다
# claass_method2.py
class Simple:
    count = 0
    def __init__(self):
        Simple.count += 1
    @classmethod
    def get_count(cls):
        return cls.count

def main():
    print(Simple.get_count())   # 0
    s = Simple()
    print(Simple.get_count())   # 1

main()
  • 클래스 메소드의 첫 번째 인자로 전달되는 것은 이 메소드의 클래스이다
# class_method3.py
class Natural:
    def __init__(self, n):
        self.n = n
    def getn(self):
        return self.n
    @classmethod
    def add(cls, n1, n2):
        return cls(n1.getn() + n2.getn())   # Natural 객체 생성 후 반환

def main():
    n1 = Natural(1)
    n2 = Natural(2)
    n3 = Natural.add(n1, n2)
    print('{0} + {1} = {2}'.format(n1.getn(), n2.getn(), n3.getn()))

main()

static 메소드보다 class 메소드가 완전 더 어울리는 경우

# international_date.py
class Date:
    def __init__(self, y, m, d):
        self.y = y
        self.m = m
        self.d = d
    def show(slef):
        print('{0}, {1}, {2}'.format(self.y, self.m, self.d))
    @classmethod
    def next_day(cls, today):
        return cls(today.y, today.m, today.d + 1)

class KDate(Date):
    def show(self):
        print('KOR: {0}, {1}, {2}'.format(self.y, self.m, self.d))

class JDate(Date):
    def show(self):
        print('JPN: {0}, {1}, {2}'.format(self.y, self.m, self.d))

def main():
    kd1 = KDate(2025, 4, 12)
    kd1.show()
    kd2 = KDate.next_day(kd1)
    kd2.show()

    jd1 = KDate(2027, 5, 19)
    jd1.show()
    jd2 = KDate.next_day(jd1)
    j2.show()
  • class 메소드는 인자로 클래스 정보를 받는다
  • 그리고 이 정보는 호출 경로에 따라서 유동적이다
  • 상속관계에서 사용 가능