나는 이렇게 학습한다/Language

Python _ @classmethod, @staticmethod 란 무엇인가?

daco2020 2022. 3. 31. 21:28
반응형

파이썬에서 클래스들을 살펴보면 가끔 뜬금없이 데코레이터가 등장하곤 합니다.

바로 @classmethod, @staticmethod 데코레이터입니다.

 

 

 

이 두 데코레이터를 왜 사용하는지 같이 살펴보겠습니다.

 

 

 

우선 다음처럼 클래스 코드를 작성하고 인스턴스를 만들겠습니다.

class Robot:
    number = '0001'
    
    def __init__(self, name):
        self.name = name
        
    def 인스턴스메서드(self):
        print(f'인스턴스메서드 호출 {self.name}')
        
    @classmethod
    def 클래스메서드(cls):
        print(f'클래스메서드 호출 {cls.number}')
    
    @staticmethod
    def 스태틱메서드():
        print('스태틱메서드 호출')
        
robot = Robot('다코')

# robot -> 인스턴스
# Robot -> 클래스

 

 


 

 

 

@classmethod는 클래스로 호출하기 위한 메서드입니다. 

class Robot:
    number = '0001'
    
    ...
    
    # @classmethod 주석처리
    def 클래스메서드(cls):
        print(f'클래스메서드 호출 {cls.number}')


robot = Robot('다코')

robot.클래스메서드() # 인스턴스로 호출
Robot.클래스메서드() # 클래스로 호출


'''
>>>
클래스메서드 호출 0001
TypeError: 클래스메서드() missing 1 required positional argument: 'cls'
'''

@classmethod를 사용하지 않고 호출을 한다면

 

인스턴스의 경우 본인이 cls의 인자로 들어가면서 호출이 되지만

클래스의 경우 cls 인자를 넣으라는 메시지를 받습니다.

(여기서 cls는 클래스 본인을 의미합니다)

 

*cls == class 본인

*self == instance 본인

 

 

물론 클래스로 호출 시 클래스를 인자로 넣어도 됩니다만,

그보다는 @classmethod를 사용하여 클래스도 호출할 수 있도록 만들 수 있습니다.

 

@classmethod를 활성화해보겠습니다.

class Robot:
    number = '0001'
    
    ...
    
    @classmethod
    def 클래스메서드(cls):
        print(f'클래스메서드 호출 {cls.number}')


robot = Robot('다코')

robot.클래스메서드() # 인스턴스로 호출
Robot.클래스메서드() # 클래스로 호출


'''
>>>
클래스메서드 호출 0001
클래스메서드 호출 0001
'''

모두 정상적으로 호출되는 것을 볼 수 있습니다.

*robot은 인스턴스인데 왜 호출될까요? robot 또한 인스턴스이자 클래스에 포함되기 때문입니다.

 

 

 

 


 

 

@staticmethod는 self, cls 인자가 필요 없는 메서드입니다.

class Robot:

    ...
    
    # @staticmethod 주석처리
    def 스태틱메서드():
        print('스태틱메서드 호출')
        
        
robot = Robot('다코')

robot.스태틱메서드() # 인스턴스로 호출
Robot.스태틱메서드() # 클래스로 호출


'''
>>>
TypeError: 스태틱메서드() takes 0 positional arguments but 1 was given
'''

인스턴스로 호출한 순간 바로 에러가 발생했습니다.

인자로 아무것도 받지 않으나 1개의 인자가 들어왔다는 내용입니다.

 

여기서 알 수 있는 것은 인스턴스로 메서드를 호출할 때,

우리가 인자를 넣지 않아도 자동으로 메서드 인자가 들어간다는 것을 알 수 있습니다.

그게 바로 self 인자인 것이죠.

 

 

이 에러를 해결하기 위해서는 두 가지 방법이 있습니다.

 

첫 번째는 위에 작성한 스태틱메서드에 self 인자를 받을 수 있도록 추가하는 것입니다. 

    def 스태틱메서드(self):
        print('스태틱메서드 호출')

 

 

이렇게하면 스태틱메서드는 인스턴스메서드가 되는 것입니다.

하지만 이 경우에는 클래스에서의 호출 시 인스턴스 인자가 필요하겠죠?

 

 

두 번째는 @staticmethod를 사용하는 것입니다.

 

class Robot:

    ...
    
    @staticmethod
    def 스태틱메서드():
        print('스태틱메서드 호출')
        
        
robot = Robot('다코')

robot.스태틱메서드() # 인스턴스로 호출
Robot.스태틱메서드() # 클래스로 호출


'''
>>>
스태틱메서드 호출
스태틱메서드 호출
'''

@staticmethod를 사용하니 인스턴스 호출도, 클래스 호출도 모두 정상 작동하였습니다.

 

@staticmethod는 인자가 필요 없는 클래스 내 정적 메서드를 실행할 수 있도록 도와줍니다. 

인스턴스와 클래스 상관없이 말이죠.

 

 

 


 

 

 

이렇듯 @classmethod, @staticmethod 객체의 메서드를 더 직관적으로 설계하고 간편하게 호출하기 위한 데코레이터입니다.

 

 

앞으로는 두 데코레이터를 만나게 되더라도 당황하지 마시고 '클래스로 호출하기 위한 메서드', 'self, cls 인자가 필요 없는 메서드' 등으로 이해하시면 되겠습니다. 

 

 

 

 

 

 

 

반응형