본문 바로가기
Python

[Python] 정적 메소드 @staticmethod, @classmethod 사용법 및 차이점

by A6K 2023. 1. 14.

파이썬에서는 @staticmethod와 @classmethod 데코레이터를 통해서 정적 메소드를 지원한다. 정적 메소드는 객체를 생성하지 않고 클래스에서 직접 접근할 수 있는 메소드를 의미한다.

instance method

인스턴스 메소드(instance method)는 객체를 통해서 호출된다. 예를 들어 다음과 같은 클래스가 있다고 해보자.

class MyClass:
    def __init__(self, data):
        self.data = data
  
    def print_data(self):
        print(self.data)


my_class = MyClass('new data')
my_class.print_data()

MyClass 클래스의 print_data() 메소드는 인스턴스 메소드다. 인스턴스 메소드는 첫 번째 인자로 자기자신을 가리키는 self를 갖는다. print_data() 메소드는 my_class라는 객체를 통해서 호출된다. 호출될 때 self는 생략된다.

static method

정적 메소드(static method)는 인스턴스를 통해서가 아닌 클래스로부터 직접 호출될 수 있다. 다음 코드를 보자.

class MyClass:
    def __init__(self, data):
        self.data = data

    @staticmethod
    def print_class_name():
        print('MyClass')


MyClass.print_class_name()

print_class_name()이라는 메소드는 정적 메소드로 선언되어 있다. print_class_name() 메소드는 MyClass라는 클래스 이름을 통해 호출 될 수 있다. (인스턴스 메소드처럼 MyClass의 객체를 통해서 호출될 수도 있다)

print_class_name() 메소드의 정의를 보면 첫 번째 인자로 self를 받지 않는 것을 볼 수 있다. 즉, 정적 메소드는 객체 별로 갖고 있는 상태 변수에는 접근할 수 없다.

class method

클래스 메소드(class method)는 정적 메소드와 유사하다. 정적 메소드처럼 클래스를 통해 호출될 수도 있고 인스턴스를 통해서 호출될 수도 있다. 

class MyClass:
    name = 'my_class'
    
    def __init__(self, data):
        self.data = data

    @classmethod
    def print_class_name(cls):
        print(cls.name)


MyClass.print_class_name()

정적 메소드와 유사하다. 다만 메소드의 첫 번째 인자로 클래스를 받아온다는 점이 다르다. 메소드 안에서 클래스 변수(cls)를 통해 클래스의 속성 값에 접근할 수 있다. 물론 정적 메소드 역시 클래스 이름을 써 넣는 방법으로(MyClass.name 호출) 클래스 속성 값에 접근할 수는 있다.

instance method와 class method 차이

동작과 사용 방법이 거의 유사한 정적 메소드와 클래스 메소드의 차이점은 상속에서 나타난다. 다음 예제 코드를 보자.

class ParentClass:
    role = "Dad"

    def __init__(self, data):
        self.data = data

    @classmethod
    def class_method_role(cls):
        print(cls.role)

    @staticmethod
    def static_method_role():
        print(ParentClass.role)


class ChildClass(ParentClass):
    role = "Son"


ChildClass.class_method_role()
ChildClass.static_method_role()

ParentClass는 role 값으로 'Dad'라는 문자열을 가지고 있다. 이 role 값을 클래스 메소드인 class_method_role()과 정적 메소드인 static_method_role()로 접근하면 동일하게 'Dad'라는 값이 출력된다.

이제 ParentClass를 상속해서 ChildClass를 생성해보자. ChildClass는 "Son"이라는 값을 갖는다. Child 클래스를 통해서 클래스 메소드를 호출하면 ChildClass의 role 값인 "Son"이 출력된다. 반면 정적메소드를 통해서 호출하면 ParentClass의 role 값인 "Dad"가 출력된다.

클래스 메소드의 인자로 받는 cls는 상속시 상속받는 자식 클래스를 가리키게 됨을 기억하면 된다.

댓글