본문 바로가기
Python

@classmethod, @staticmethod (파이썬 매서드 데코레이터)

by yororing 2024. 7. 1.

00 개요

  • 파이썬 파일들을 보면 @classmethod, @staticmethod와 같은 데코레이터가 등장하는데 이에 대해 정리하고자 함
  • 일단 클래스에서 사용되는 각 메소드 종류에 대해 알아보기
  • 메소드 종류: 인스턴스 메서드, 정적 메서드, 클래스 메서드

01 instance method 인스턴스 매서드

1. 인스턴스 매서드의 정의

  • 가장 기본이 되는 클래스의 메서드
  • 첫번째 인자로는 항상 self를 적고, 해당 클래스의 인스턴스 값이 넘어옴
# testFile.py 내용

class Blog:
    def __init__(self, name="Pearl's blog"):
        self.name = name
    
    # 인스턴스 메소드
    def print_name(self):
        print(self.name)

blog = Blog()
print(blog.print_name())

02 static method 정적 매서드

0. 정적 매서드 이해하기

# testFile.py 내용
class Blog:
    def __init__(self, name = "Pearl's Blog"):
        self.name = name
        
    # @staticmethod 주석처리
    def my_매서드():    # self 인자 미사용, 인자로 아무것도 받지 않도록 설정
        print("my_매서드 호출")

blog = Blog()
print("인스턴스로 호출:")
blog.my_매서드()
print("클래스로 호출:")
Blog.my_매서드()

  • my_매서드()를 인스턴스로 호출한 순간 바로 에러 발생
  • ERROR 내용: 위에서 생성된 my_매서드()는 인자로 아무것도 받지 않도록 정의되어있으나 1개의 인자가 들어왔다는 내용 
  • 즉, 인스턴스로 매서드 호출 시 우리가 인자를 넣지 않아도 자동으로 매서드 인자가 들어간다는 것 확인
    • 그게 바로 self 인자
  • 해결 방법 2가지: 1) my_매서드()에 self 인자를 받을 수 있도록 설정, 또는 2) @staticmethod 사용
  • 1) my_매서드()에 self 인자를 받을 수 있도록 설정
def my_매서드(self): # self 인자 추가
    print("my_매서드 호출")
# testFile.py 내용
class Blog:
    def __init__(self, name = "Pearl's Blog"):
        self.name = name
        
    # @staticmethod 주석처리
    def my_매서드(self):        # self 인자 사용
        print("my_매서드 호출 성공")

blog = Blog()
print("인스턴스로 호출:")
blog.my_매서드()
print("클래스로 호출:")
Blog.my_매서드()

  • 이럴 경우 my_매서드()는 인스턴스 매서드 (self를 인자로 받는 매서드)가 되는 것
  • 하지만 위와 같이 클래스로 호출 시 에러 발생
  • ERROR 내용: Blog.my_매서드()에 1개의 인자가 들어와야 하는데 안 들어왔다는 내용
  • 다음과 같이 인자를 넣어주면 해결됨 (맨 마지막 줄)
# testFile.py 내용
class Blog:
    def __init__(self, name = "Pearl's Blog"):
        self.name = name
        
    # @staticmethod 주석처리
    def my_매서드(self):
        print("my_매서드 호출 성공")

blog = Blog()
print("인스턴스로 호출:")
blog.my_매서드()
print("클래스로 호출:")
Blog.my_매서드("인자")        # 인자 추가

  • 2) @staticmethod 사용
@staticmethod   # @staticmethod 데코레이터 추가
def my_매서드():
    print("my_매서드 호출 성공")
# testFile.py 내용
class Blog:
    def __init__(self, name = "Pearl's Blog"):
        self.name = name
        
    @staticmethod          # @staticmethod 데코레이터 추가
    def my_매서드():
        print("my_매서드 호출 성공")

blog = Blog()
print("인스턴스로 호출:")
blog.my_매서드()
print("클래스로 호출:")
Blog.my_매서드()

  • @staticmethod를 사용하니 인스턴스로서의 호출(i.e., 인스턴스.매서드() )도, 클래스로서의 호출(i.e., 클래스.매서드() )도 모두 정상적으로 작동하는 것 확인
  • 즉, @staticmethod는 인자가 필요 없는 클래스 내 정적 매서드를 실행할 수 있도록 도와주는 데코레이터 (인스턴스/클래스 상관 없이!)

1. 정적 매서드의 정의

  • 클래스의 인스턴스 매서드에 @staticmethod 데코레이터를 사용하면 정적 매서드가 됨
  • 인스턴스 매서드에서 사용되는 self 인자 또는 클래스 매서드에서 사용되는 cls 인자 불필요
  • 즉, self, cls 인자가 필요 없는 메서드
  • 인스턴스의 속성에 접근 불가
# testFile.py 내용
class Blog:
    def __init__(self, name = "Pearl's Blog")
        self.name = name
        
    # 정적 매서드
    @staticmethod
    def to_upper(text: str):    # self 인자 미사용
        print(text.upper())

blog = Blog()
print(blog.name)
print(Blog.to_upper(blog.name))

2. 정적 매서드의 사용

  • 주로 유틸리티성 함수를 위한 용도로 사용됨
  • 클래스의 어떤 속성에도 변화를 주지 않는 함수이며 입력이 들어오면 항상 같은 출력을 반환하는 순수 함수들이 이에 해당

03 class method 클래스 매서드

1. 클래스 매서드의 정의

  • 클래스의 인스턴스 매서드에 @classmethod 데코레이터를 사용하면 클래스 매서드가 됨
  • 첫번째 인자로는 항상 cls를 적고, 해당 클래스 자체가 넘어옴
  • 즉, 클래스를 호출하기 위한 매서드 
  • 따라서 인스턴스 매서드와 달리 해당 클래스의 속성에 접근 가능
# testFile.py

class Blog:
    platform: str = "tistory"
    
    def __init__(self, name = "Pearl's Blog"):
        self.name = name
    
    # 클래스 매서드 - 클래스 속성 변경
    @classmethod
    def change_platform(cls, platform: str):
        cls.platform = platform
    
    # 클래스 매서드 - 팩토리 매서드 사용
    @classmethod
    def from_dict(cls, dic: dict):
        return cls(dic["name"])
        

blog = Blog()
print("class' platform: %s" % blog.platform)

Blog.change_platform("naver")
print("change_platform (instance): %s" % blog.platform)  # 인스턴스로 호출
print("change_platform (class): %s" % Blog.platform)  # 클래스로 호출
blog2 = Blog.from_dict({"name": "Dayoon's Blog"})
print("from_dict: %s" % blog2.name)

  • blog는 인스턴스인데 호출되는 이유: blog 또한 인스턴스이자 클래스에 포함되기 때문
    • blog = Blog()

2. 클래스 매서드의 사용

1) 클래스 속성 접근

  • 클래스 속성에 접근하거나 변경하려는 경우 @classmethod 사용 가능
  • change_platform() 함수의 경우 클래스의 속성인 platform의 값에 접근하고 변경하는 방식으로 사용됨

2) 팩토리 매서드 (factory method)로 사용

  • 특정한 입력 형식으로부터 인스턴스를 생성하려는 경우 @classmethod 사용 가능
  • from_dict() 함수의 경우 딕셔너리로부터 값을 받아와 인스턴스를 생성하기 위해 생성자를 wrapping하는 용도로 사용됨

참조

  1. https://leffept.tistory.com/441#classmethod%--%EB%-E%--%-F 
  2. https://daco2020.tistory.com/281
  3.  
  4.